From 89908cdef35e8422811402a3e143b45ff04d00ac Mon Sep 17 00:00:00 2001 From: Michael <12646562+mbround18@users.noreply.github.com> Date: Sun, 9 May 2021 01:20:56 -0700 Subject: [PATCH] Custom Release Train (#353) --- .auto/plugins/release.ts | 133 ++++++++++++++++++++++++++++++++++ .autorc | 2 +- .github/workflows/release.yml | 21 ++---- package.json | 9 ++- yarn.lock | 19 ++++- 5 files changed, 167 insertions(+), 17 deletions(-) create mode 100644 .auto/plugins/release.ts diff --git a/.auto/plugins/release.ts b/.auto/plugins/release.ts new file mode 100644 index 0000000..3f08652 --- /dev/null +++ b/.auto/plugins/release.ts @@ -0,0 +1,133 @@ +import { + Auto, + determineNextVersion, + execPromise, + IPlugin, + getCurrentBranch, + DEFAULT_PRERELEASE_BRANCHES, +} from "@auto-it/core"; +import { inc, ReleaseType } from "semver"; + +export default class GitTagPlugin implements IPlugin { + /** The name of the plugin */ + name = "release"; + + /** Tap into auto plugin points. */ + apply(auto: Auto) { /** Get the latest tag in the repo, if none then the first commit */ + async function getTag() { + try { + return await auto.git!.getLatestTagInBranch(); + } catch (error) { + return auto.prefixRelease("0.0.0"); + } + } + + auto.hooks.getPreviousVersion.tapPromise(this.name, async () => { + if (!auto.git) { + throw new Error( + "Can't calculate previous version without Git initialized!" + ); + } + + return getTag(); + }); + + auto.hooks.version.tapPromise( + this.name, + async ({ bump, dryRun, quiet }) => { + if (!auto.git) { + return; + } + + const lastTag = await getTag(); + const newTag = inc(lastTag, bump as ReleaseType); + + if (!newTag) { + auto.logger.log.info("No release found, doing nothing"); + return; + } + + const prefixedTag = auto.prefixRelease(newTag); + + if (dryRun) { + if (quiet) { + console.log(prefixedTag); + } else { + auto.logger.log.info(`Would have published: ${prefixedTag}`); + } + + return; + } + + auto.logger.log.info(`Tagging new tag: ${lastTag} => ${prefixedTag}`); + await execPromise("git", [ + "tag", + prefixedTag, + "-m", + `"Update version to ${prefixedTag}"`, + ]); + } + ); + + auto.hooks.next.tapPromise( + this.name, + async (preReleaseVersions, { bump, dryRun }) => { + if (!auto.git) { + return preReleaseVersions; + } + + const prereleaseBranches = + auto.config?.prereleaseBranches ?? DEFAULT_PRERELEASE_BRANCHES; + const branch = getCurrentBranch() || ""; + const prereleaseBranch = prereleaseBranches.includes(branch) + ? branch + : prereleaseBranches[0]; + const lastRelease = await auto.git.getLatestRelease(); + const current = + (await auto.git.getLastTagNotInBaseBranch(prereleaseBranch)) || + (await auto.getCurrentVersion(lastRelease)); + const prerelease = auto.prefixRelease( + determineNextVersion(lastRelease, current, bump, prereleaseBranch) + ); + + preReleaseVersions.push(prerelease); + + if (dryRun) { + return preReleaseVersions; + } + + await execPromise("git", [ + "tag", + prerelease, + "-m", + `"Tag pre-release: ${prerelease}"`, + ]); + await execPromise("git", ["push", auto.remote, branch, "--tags"]); + + return preReleaseVersions; + } + ); + + auto.hooks.publish.tapPromise(this.name, async () => { + auto.logger.log.info("Pushing new tag to GitHub"); + if (process.env.GITHUB_REPOSITORY.length === 0) { + throw new Error("Failed to find GITHUB_REPOSITORY in environment!") + } + + await execPromise("git", [ + "remote", + "set-url", + "origin", + `git@github.com:${process.env.GITHUB_REPOSITORY}.git`, + ]); + + await execPromise("git", [ + "push", + "--follow-tags", + "--set-upstream", + "origin", + getCurrentBranch() || auto.baseBranch, + ]); + }); + } +} diff --git a/.autorc b/.autorc index 294f440..a15a500 100644 --- a/.autorc +++ b/.autorc @@ -1,6 +1,6 @@ { "plugins": [ - "git-tag", + ".auto/plugins/release.ts", "all-contributors" ], "owner": "mbround18", diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5a4223e..01babde 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,21 +27,16 @@ jobs: - name: Yarn install run: yarn install --frozen-lockfile - - name: Temporarily disable "include administrators" branch protection - uses: benjefferies/branch-protection-bot@1.0.5 - if: ${{ always() && github.ref == 'refs/heads/main' }} + - name: Install SSH key + uses: shimataro/ssh-key-action@v2 with: - branch: main - access-token: ${{ secrets.GH_TOKEN }} + key: ${{ secrets.SSH_KEY }} + name: id_rsa # optional + known_hosts: ${{ secrets.KNOWN_HOSTS }} + if_key_exists: replace - name: Create Release run: | - yarn auto shipit + yarn release + - - name: Enable "include administrators" branch protection - uses: benjefferies/branch-protection-bot@1.0.5 - # Force to always run this step to ensure "include administrators" is always turned back on - if: ${{ always() && github.ref == 'refs/heads/main' }} - with: - branch: main - access-token: ${{ secrets.GH_TOKEN }} diff --git a/package.json b/package.json index 049d517..21762e0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,13 @@ "devDependencies": { "@auto-it/all-contributors": "10.27.0", "@auto-it/git-tag": "10.27.0", - "auto": "10.27.0" + "auto": "10.27.0", + "@types/node": "^15.0.2" + }, + "dependencies": { + "@auto-it/core": "^10.27.0", + "@types/semver": "^7.3.5", + "semver": "^7.3.5", + "typescript": "^4.2.4" } } diff --git a/yarn.lock b/yarn.lock index 9b38917..8b7aa04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,7 +25,7 @@ resolved "https://registry.yarnpkg.com/@auto-it/bot-list/-/bot-list-10.27.0.tgz#39264ca2974f227a8e7b0f327e7601eba2a23b7d" integrity sha512-KIiWpm8h2PWJEZOKN+bu+O8/16IdogQlEpmXT+I0ipwB9mnulliCQwYdi4OleE9Y7wedd7WTszG4tbRIRqyW+A== -"@auto-it/core@10.27.0": +"@auto-it/core@10.27.0", "@auto-it/core@^10.27.0": version "10.27.0" resolved "https://registry.yarnpkg.com/@auto-it/core/-/core-10.27.0.tgz#2f8d3480b1729dbd5c43d629689090f4193324ef" integrity sha512-vsaj4xsQXLYhsggGLygK+8VRZEc5M4HwAc9u4aKb6ATzN3oT3uABW+xVBjeKiA8wX5JAhAWP9yQy/IbPwW5otw== @@ -313,11 +313,21 @@ resolved "https://registry.yarnpkg.com/@types/command-line-usage/-/command-line-usage-5.0.1.tgz#99424950da567ba67b6b65caee57ff03c4e751ec" integrity sha512-/xUgezxxYePeXhg5S04hUjxG9JZi+rJTs1+4NwpYPfSaS7BeDa6tVJkH6lN9Cb6rl8d24Fi2uX0s0Ngg2JT6gg== +"@types/node@^15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.2.tgz#51e9c0920d1b45936ea04341aa3e2e58d339fb67" + integrity sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/semver@^7.3.5": + version "7.3.5" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.5.tgz#74deebbbcb1e86634dbf10a5b5e8798626f5a597" + integrity sha512-iotVxtCCsPLRAvxMFFgxL8HD2l4mAZ2Oin7/VJ2ooWO0VOK4EGOGmZWZn1uCq7RofR3I/1IOSjCHlFT71eVK0Q== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -1508,7 +1518,7 @@ rxjs@^6.6.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^7.0.0: +semver@^7.0.0, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -1706,6 +1716,11 @@ typescript-memoize@^1.0.0-alpha.3: resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.0.1.tgz#0a8199aa28f6fe18517f6e9308ef7bfbe9a98d59" integrity sha512-oJNge1qUrOK37d5Y6Ly2txKeuelYVsFtNF6U9kXIN7juudcQaHJQg2MxLOy0CqtkW65rVDYuTCOjnSIVPd8z3w== +typescript@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" + integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4"