From cf7ec0bfe3d580a81bc95ea658a262fa0d94dd5f Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Tue, 14 Mar 2023 23:23:25 +0300 Subject: [PATCH] ci: migrate to gh-actions (#139) --- .github/workflows/ci.yaml | 61 +++++++++++++++++++++++++++ .travis.yml => .travis.disabled.yml | 0 package.json | 4 +- test/bin/cli.test.js | 16 ++++++- test/helpers/git.js | 43 ++++++++++--------- test/lib/git.test.js | 12 ++++-- test/lib/multiSemanticRelease.test.js | 50 ++++++++++++---------- 7 files changed, 138 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/ci.yaml rename .travis.yml => .travis.disabled.yml (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..e7e06b5c --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,61 @@ +# This is a Github Workflow that runs tests on any push or pull request. +# If the tests pass and this is a push to the master branch it also runs Semantic Release. +name: CI +on: [push, pull_request] +jobs: + test_pr: + if: github.event_name == 'pull_request' + name: Test PR (Node v${{ matrix.node-version }}, OS ${{ matrix.os }}) + strategy: + matrix: + os: [ ubuntu-22.04 ] + node-version: [ 14, 18 ] + + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Fetch deps + run: yarn + + - name: Run tests + # Workaround like TRAVIS_PULL_REQUEST_BRANCH=master + run: | + git branch master + yarn test + + release: + name: Release + # https://github.community/t/trigger-job-on-tag-push-only/18076 + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Fetch deps + run: yarn + + - name: Semantic Release + run: npx semantic-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }} + GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }} + GIT_COMMITTER_NAME: ${{ secrets.GIT_COMMITTER_NAME }} + GIT_COMMITTER_EMAIL: ${{ secrets.GIT_COMMITTER_EMAIL }} diff --git a/.travis.yml b/.travis.disabled.yml similarity index 100% rename from .travis.yml rename to .travis.disabled.yml diff --git a/package.json b/package.json index 05c57bbc..a2fe15ef 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "bin" ], "scripts": { - "watch": "TRAVIS_PULL_REQUEST_BRANCH=master jest --watchAll", - "jest": "TRAVIS_PULL_REQUEST_BRANCH=master jest --coverage", + "watch": "jest --watchAll", + "jest": "jest --coverage", "lint": "eslint ./", "lint:fix": "eslint --fix ./", "test": "yarn lint && yarn jest", diff --git a/test/bin/cli.test.js b/test/bin/cli.test.js index ebe7d85b..5b1f0f2d 100644 --- a/test/bin/cli.test.js +++ b/test/bin/cli.test.js @@ -11,6 +11,12 @@ const { gitGetTags, } = require("../helpers/git"); +const env = { + GH_TOKEN: "test", + NPM_TOKEN: "test", + PATH: process.env.PATH, +}; + // Tests. describe("multi-semantic-release CLI", () => { test("Initial commit (changes in all packages)", async () => { @@ -25,7 +31,7 @@ describe("multi-semantic-release CLI", () => { const filepath = `${__dirname}/../../bin/cli.js`; // Run via command line. - const out = (await execa("node", [filepath], { cwd })).stdout; + const out = (await execa("node", [filepath], { cwd, env, extendEnv: false })).stdout; expect(out).toMatch("Started multirelease! Loading 4 packages..."); expect(out).toMatch("Released 4 of 4 packages, semantically!"); }); @@ -41,7 +47,13 @@ describe("multi-semantic-release CLI", () => { const filepath = `${__dirname}/../../bin/cli.js`; // Run via command line. - const out = (await execa("node", [filepath, "--ignore-packages=packages/c/**,packages/d/**"], { cwd })).stdout; + const out = ( + await execa("node", [filepath, "--ignore-packages=packages/c/**,packages/d/**"], { + cwd, + env, + extendEnv: false, + }) + ).stdout; expect(out).toMatch("Started multirelease! Loading 2 packages..."); expect(out).toMatch("Released 2 of 2 packages, semantically!"); }); diff --git a/test/helpers/git.js b/test/helpers/git.js index 69ee4d53..70f23d1e 100644 --- a/test/helpers/git.js +++ b/test/helpers/git.js @@ -9,6 +9,7 @@ const execa = require("execa"); const fileUrl = require("file-url"); const gitLogParser = require("git-log-parser"); const { array: getStreamArray } = require("get-stream"); +const env = {}; /** * @typedef {Object} Commit @@ -32,12 +33,16 @@ function gitInit(branch = "master") { // Init Git in a temp directory. const cwd = tempy.directory(); - execa.sync("git", ["init"], { cwd }); - execa.sync("git", ["checkout", "-b", branch], { cwd }); + execa.sync("git", ["init", "-b", "master"], { cwd, env }); + execa.sync("git", ["checkout", "-b", branch], { cwd, env }); // Disable GPG signing for commits. gitConfig(cwd, "commit.gpgsign", false); + // Set user profile. + gitConfig(cwd, "user.name", "Test"); + gitConfig(cwd, "user.email", "test@example.com"); + // Return directory. return cwd; } @@ -46,12 +51,12 @@ function gitInit(branch = "master") { * Create a remote Git repository. * _Created in a temp folder._ * - * @return {Promise} Promise that resolves to string URL of the of the remote origin. + * @return {Promise} Promise that resolves to string URL of the remote origin. */ function gitInitRemote() { // Init bare Git repository in a temp directory. const cwd = tempy.directory(); - execa.sync("git", ["init", "--bare"], { cwd }); + execa.sync("git", ["init", "--bare"], { cwd, env }); // Turn remote path into a file URL. const url = fileUrl(cwd); @@ -76,15 +81,15 @@ function gitInitOrigin(cwd, releaseBranch = null) { const url = gitInitRemote(); // Set origin on local repo. - execa.sync("git", ["remote", "add", "origin", url], { cwd }); + execa.sync("git", ["remote", "add", "origin", url], { cwd, env }); // Set up a release branch. Return to master afterwards. if (releaseBranch) { - execa.sync("git", ["checkout", "-b", releaseBranch], { cwd }); - execa.sync("git", ["checkout", "master"], { cwd }); + execa.sync("git", ["checkout", "-b", releaseBranch], { cwd, env }); + execa.sync("git", ["checkout", "master"], { cwd, env }); } - execa.sync("git", ["push", "--all", "origin"], { cwd }); + execa.sync("git", ["push", "--all", "origin"], { cwd, env }); // Return URL for remote. return url; @@ -104,7 +109,7 @@ function gitAdd(cwd, file = ".") { check(cwd, "cwd: absolute"); // Await command. - execa.sync("git", ["add", file], { cwd }); + execa.sync("git", ["add", file], { cwd, env }); } // Commits. @@ -123,7 +128,7 @@ function gitCommit(cwd, message) { check(message, "message: string+"); // Await the command. - execa.sync("git", ["commit", "-m", message, "--no-gpg-sign"], { cwd }); + execa.sync("git", ["commit", "-m", message, "--no-gpg-sign"], { cwd, env }); // Return HEAD SHA. return gitGetHead(cwd); @@ -167,7 +172,7 @@ function gitPush(cwd, remote = "origin", branch = "master") { check(branch, "branch: lower"); // Await command. - execa.sync("git", ["push", "--tags", remote, `HEAD:${branch}`], { cwd }); + execa.sync("git", ["push", "--tags", remote, `HEAD:${branch}`], { cwd, env }); } // Branches. @@ -185,7 +190,7 @@ function gitBranch(cwd, branch) { check(branch, "branch: lower"); // Await command. - execa.sync("git", ["branch", branch], { cwd }); + execa.sync("git", ["branch", branch], { cwd, env }); } /** @@ -201,7 +206,7 @@ function gitCheckout(cwd, branch) { check(branch, "branch: lower"); // Await command. - execa.sync("git", ["checkout", branch], { cwd }); + execa.sync("git", ["checkout", branch], { cwd, env }); } // Hashes. @@ -217,7 +222,7 @@ function gitGetHead(cwd) { check(cwd, "cwd: absolute"); // Await command and return HEAD SHA. - return execa.sync("git", ["rev-parse", "HEAD"], { cwd }).stdout; + return execa.sync("git", ["rev-parse", "HEAD"], { cwd, env }).stdout; } // Tags. @@ -237,7 +242,7 @@ function gitTag(cwd, tagName, hash = undefined) { check(hash, "hash: alphanumeric{40}?"); // Run command. - execa.sync("git", hash ? ["tag", "-f", tagName, hash] : ["tag", tagName], { cwd }); + execa.sync("git", hash ? ["tag", "-f", tagName, hash] : ["tag", tagName], { cwd, env }); } /** @@ -253,7 +258,7 @@ function gitGetTags(cwd, hash) { check(hash, "hash: alphanumeric{40}"); // Run command. - return execa.sync("git", ["describe", "--tags", "--exact-match", hash], { cwd }).stdout; + return execa.sync("git", ["describe", "--tags", "--exact-match", hash], { cwd, env }).stdout; } /** @@ -269,7 +274,7 @@ function gitGetTagHash(cwd, tagName) { check(tagName, "tagName: string+"); // Run command. - return execa.sync("git", ["rev-list", "-1", tagName], { cwd }).stdout; + return execa.sync("git", ["rev-list", "-1", tagName], { cwd, env }).stdout; } // Configs. @@ -288,7 +293,7 @@ function gitConfig(cwd, name, value) { check(name, "name: string+"); // Run command. - execa.sync("git", ["config", "--add", name, value], { cwd }); + execa.sync("git", ["config", "--add", name, value], { cwd, env }); } /** @@ -304,7 +309,7 @@ function gitGetConfig(cwd, name) { check(name, "name: string+"); // Run command. - execa.sync("git", ["config", name], { cwd }).stdout; + execa.sync("git", ["config", name], { cwd, env }).stdout; } // Exports. diff --git a/test/lib/git.test.js b/test/lib/git.test.js index d437d099..3cc083d6 100644 --- a/test/lib/git.test.js +++ b/test/lib/git.test.js @@ -4,6 +4,12 @@ const { copyDirectory, createNewTestingFiles } = require("../helpers/file"); const { gitInit, gitCommitAll, gitInitOrigin, gitPush } = require("../helpers/git"); const { getTags } = require("../../lib/git"); +const env = { + GH_TOKEN: "test", + NPM_TOKEN: "test", + PATH: process.env.PATH, +}; + test("Fetch all tags on master after two package release", async () => { const packages = ["packages/c/", "packages/d/"]; @@ -25,7 +31,7 @@ test("Fetch all tags on master after two package release", async () => { { branches: [{ name: "master" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); const tags = getTags("master", { cwd }).sort(); @@ -53,7 +59,7 @@ test("Fetch only prerelease tags", async () => { { branches: [{ name: "master" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Add new testing files for a new release. @@ -73,7 +79,7 @@ test("Fetch only prerelease tags", async () => { { branches: [{ name: "master", prerelease: "beta" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); const tags = getTags("master", { cwd }, ["beta"]).sort(); diff --git a/test/lib/multiSemanticRelease.test.js b/test/lib/multiSemanticRelease.test.js index 61c02e9e..0034c7f2 100644 --- a/test/lib/multiSemanticRelease.test.js +++ b/test/lib/multiSemanticRelease.test.js @@ -20,6 +20,12 @@ beforeEach(() => { require.cache = {}; // Clear the require cache so modules are loaded fresh. }); +const env = { + GH_TOKEN: "test", + NPM_TOKEN: "test", + PATH: process.env.PATH, +}; + // Tests. describe("multiSemanticRelease()", () => { test("Initial commit (changes in all packages)", async () => { @@ -45,7 +51,7 @@ describe("multiSemanticRelease()", () => { `packages/d/package.json`, ], {}, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -167,7 +173,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -289,7 +295,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Add new testing files for a new release. @@ -308,7 +314,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -373,7 +379,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Add new testing files for a new release. @@ -393,7 +399,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "beta" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -465,7 +471,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Add new testing files for a new release. @@ -484,7 +490,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -629,7 +635,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Add new testing files for a new release. @@ -647,7 +653,7 @@ describe("multiSemanticRelease()", () => { { branches: [{ name: "master", prerelease: "dev" }, { name: "release" }], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -823,7 +829,7 @@ describe("multiSemanticRelease()", () => { `packages/b/package.json`, ], {}, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -878,7 +884,7 @@ describe("multiSemanticRelease()", () => { `packages/a/package.json`, ], {}, - { cwd, stdout, stderr }, + { cwd, stdout, stderr, env }, { deps: {}, dryRun: false } ); @@ -1014,7 +1020,7 @@ describe("multiSemanticRelease()", () => { `packages/a/package.json`, ], {}, - { cwd, stdout, stderr }, + { cwd, stdout, stderr, env }, { sequentialInit: true, deps: {} } ); @@ -1058,7 +1064,7 @@ describe("multiSemanticRelease()", () => { const result = await multiSemanticRelease( [`packages/a/package.json`, `packages/c/package.json`], {}, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Not reached. @@ -1099,7 +1105,7 @@ describe("multiSemanticRelease()", () => { plugins: ["@semantic-release/release-notes-generator", plugin], analyzeCommits: ["@semantic-release/commit-analyzer"], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Check calls. @@ -1129,7 +1135,7 @@ describe("multiSemanticRelease()", () => { const [aResult, bResult] = await multiSemanticRelease( [`packages/a/package.json`, `packages/b/package.json`], {}, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Check no stderr @@ -1172,7 +1178,7 @@ describe("multiSemanticRelease()", () => { }, ], }, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Not reached. @@ -1271,7 +1277,7 @@ describe("multiSemanticRelease()", () => { const result = await multiSemanticRelease( [`packages/a/package.json`, `packages/b/package.json`], {}, - { cwd, stdout, stderr }, + { cwd, stdout, stderr, env }, { deps: { bump: "satisfy" }, dryRun: false } ); @@ -1366,7 +1372,7 @@ describe("multiSemanticRelease()", () => { `packages/e/package.json`, ], {}, - { cwd, stdout, stderr } + { cwd, stdout, stderr, env } ); // Get stdout and stderr output. @@ -1513,7 +1519,7 @@ describe("multiSemanticRelease()", () => { `packages/e/package.json`, ], {}, - { cwd, stdout, stderr }, + { cwd, stdout, stderr, env }, { ignorePrivatePackages: true, deps: {} } ); @@ -1645,7 +1651,7 @@ describe("multiSemanticRelease()", () => { `packages/d/package.json`, ], {}, - { cwd, stdout, stderr }, + { cwd, stdout, stderr, env }, { deps: { bump: strategy, prefix } } ); @@ -1776,7 +1782,7 @@ describe("multiSemanticRelease()", () => { `packages/d/package.json`, ], {}, - { cwd, stdout, stderr }, + { cwd, stdout, stderr, env }, { deps: { bump: strategy, prefix } } );