diff --git a/README.md b/README.md index d913c89..91a4237 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # @open-sauced/release > [**semantic-release**](https://github.com/semantic-release/semantic-release) shareable config to publish to `npm` and/or `ghcr`. -> now with alpha and beta pre-releases +> now with alpha and beta pre-releases [![Commits](https://img.shields.io/github/commit-activity/w/open-sauced/release?style=flat)](https://github.com/open-sauced/release/pulse) [![Issues](https://img.shields.io/github/issues/open-sauced/release.svg?style=flat)](https://github.com/open-sauced/release/issues) @@ -34,6 +34,7 @@ This shareable configuration use the following plugins: ## ๐Ÿ–ฅ๏ธ Requirements Most important limitations are: + - `GITHUB_TOKEN` for everything - `NPM_TOKEN` for public `npm` library - `docker` containers need to be built beforehand @@ -41,6 +42,7 @@ Most important limitations are: You can skip here if you are using elevated [Private Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token), however we don't recommend going down that path. No force push or admin cherries branch protections for the following branches: + - `main` - required - `alpha` - optional, pre-release branch - `beta` - optional, pre-release branch @@ -52,7 +54,7 @@ If you use more than the main branch, optionally create an environment that is l We are using `production` in our examples, if you copy paste them you will find this new environment generated in your settings! ๐Ÿ• -## ๐Ÿงช GitHub actions usage +## ๐Ÿงช GitHub actions usage Since version 3 it is possible to use semantic-release without any trace of it or the open-sauced configuration anywhere in the dependency tree. @@ -91,7 +93,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: 'โ™ป๏ธ cleanup' + - name: "โ™ป๏ธ cleanup" run: | echo ${{ env.RELEASE_TAG }} echo ${{ env.RELEASE_VERSION }} @@ -132,7 +134,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: 'โ™ป๏ธ cleanup' + - name: "โ™ป๏ธ cleanup" run: | echo ${{ steps.semantic-release.outputs.release-tag }} echo ${{ steps.semantic-release.outputs.release-version }} @@ -164,7 +166,9 @@ npx semantic-release If you do not plan to publish to `npm` _or_ `ghcr` but still want to cut tags and GitHub releases with this system, you can specify `SKIP_NPM_PUBLISH` and -`SKIP_DOCKER_PUBLISH`. This will still publish releases, generate semver tags, +`SKIP_DOCKER_PUBLISH`. Also, if you want to set up this action in a Github Action repo and do not plan on using Docker, you can specify `SKIP_ACTION_REPLACEMENT` to skip the action replacement step. + +This will still publish releases, generate semver tags, and generate GitHub release notes. But it will skip attempting to publish Then, in a separate GitHub action, you can watch for the releases and upload assets @@ -200,7 +204,7 @@ jobs: uses: open-sauced/release@v2 outputs: - release-tag: ${{ steps.semantic-release.outputs.release-tag }} + release-tag: ${{ steps.semantic-release.outputs.release-tag }} build: needs: @@ -210,20 +214,20 @@ jobs: contents: write # release changes require contents write steps: - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: 1.21 - - - name: Check out code - uses: actions/checkout@v3 - - - name: Build and upload Go binaries - env: - GH_TOKEN: ${{ github.token }} - run: | - go build -o build/my-go-binary - gh release upload ${{ needs.release.outputs.release-tag }} build/my-go-binary + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.21 + + - name: Check out code + uses: actions/checkout@v3 + + - name: Build and upload Go binaries + env: + GH_TOKEN: ${{ github.token }} + run: | + go build -o build/my-go-binary + gh release upload ${{ needs.release.outputs.release-tag }} build/my-go-binary ``` ## ๐Ÿ”ง Configuration @@ -254,7 +258,7 @@ If you have a `manifest.json` present, our config will attempt to adjust the `ve ### Docker -Unless you have a `Dockerfile` present in your root folder, this module is not added to the release config. +Unless you have a `Dockerfile` present in your root folder, this module is not added to the release config. If you have a `Dockerfile` present, our config will attempt to push to `ghcr.io`. diff --git a/release.config.js b/release.config.js index 7ec3842..c451539 100644 --- a/release.config.js +++ b/release.config.js @@ -1,11 +1,11 @@ const { existsSync } = require("node:fs"); -const { execSync } = require('node:child_process'); +const { execSync } = require("node:child_process"); const log = require("npmlog"); log.info(`Executing semantic-release config setup`); const releaseConfig = { - "branches": [ + branches: [ // maintenance releases "+([0-9])?(.{+([0-9]),x}).x", @@ -17,20 +17,16 @@ const releaseConfig = { // pre-releases { name: "beta", - prerelease: true + prerelease: true, }, { name: "alpha", - prerelease: true - } + prerelease: true, + }, ], plugins: [], -} -const noteKeywords = [ - "BREAKING CHANGE", - "BREAKING CHANGES", - "BREAKING" -]; +}; +const noteKeywords = ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"]; const { GITHUB_SHA, GITHUB_REPOSITORY, @@ -42,11 +38,12 @@ const { NPM_PACKAGE_ROOT, SKIP_CHANGELOG = false, SKIP_DOCKER_PUBLISH = false, - SKIP_NPM_PUBLISH = false + SKIP_NPM_PUBLISH = false, + SKIP_ACTION_REPLACEMENT = false, } = process.env; const [owner, repo] = String(GITHUB_REPOSITORY).toLowerCase().split("/"); const addPlugin = (plugin, options) => { - log.info(`${plugin} enabled with${options && ' options:' || 'out options'}`); + log.info(`${plugin} enabled with${(options && " options:") || "out options"}`); options && log.info(null, options); return releaseConfig.plugins.push([plugin, options]); }; @@ -67,59 +64,59 @@ try { log.info(`Adding semantic-release config plugins`); addPlugin("@semantic-release/commit-analyzer", { - "preset": "conventionalcommits", - "releaseRules": [ - {breaking: true, release: "major"}, - {type: "feat", release: "minor"}, - {type: "fix", release: "patch"}, - {type: "perf", release: "patch"}, - {type: "revert", release: "patch"}, - {type: "docs", release: "minor"}, - {type: "style", release: "patch"}, - {type: "refactor", release: "patch"}, - {type: "test", release: "patch"}, - {type: "build", release: "patch"}, - {type: "ci", release: "patch"}, - {type: "chore", release: false} + preset: "conventionalcommits", + releaseRules: [ + { breaking: true, release: "major" }, + { type: "feat", release: "minor" }, + { type: "fix", release: "patch" }, + { type: "perf", release: "patch" }, + { type: "revert", release: "patch" }, + { type: "docs", release: "minor" }, + { type: "style", release: "patch" }, + { type: "refactor", release: "patch" }, + { type: "test", release: "patch" }, + { type: "build", release: "patch" }, + { type: "ci", release: "patch" }, + { type: "chore", release: false }, ], - "parserOpts": { - noteKeywords - } + parserOpts: { + noteKeywords, + }, }); addPlugin("@semantic-release/release-notes-generator", { - "preset": "conventionalcommits", - "parserOpts": { - noteKeywords + preset: "conventionalcommits", + parserOpts: { + noteKeywords, }, - "writerOpts": { - "commitsSort": ["subject", "scope"] + writerOpts: { + commitsSort: ["subject", "scope"], }, - "presetConfig": { + presetConfig: { types: [ - {type: "feat", section: "๐Ÿ• Features"}, - {type: "feature", section: "๐Ÿ• Features"}, - {type: "fix", section: "๐Ÿ› Bug Fixes"}, - {type: "perf", section: "๐Ÿ”ฅ Performance Improvements"}, - {type: "revert", section: "โฉ Reverts"}, - {type: "docs", section: "๐Ÿ“ Documentation"}, - {type: "style", section: "๐ŸŽจ Styles"}, - {type: "refactor", section: "๐Ÿง‘โ€๐Ÿ’ป Code Refactoring"}, - {type: "test", section: "โœ… Tests"}, - {type: "build", section: "๐Ÿค– Build System"}, - {type: "ci", section: "๐Ÿ” Continuous Integration"} - ] - } + { type: "feat", section: "๐Ÿ• Features" }, + { type: "feature", section: "๐Ÿ• Features" }, + { type: "fix", section: "๐Ÿ› Bug Fixes" }, + { type: "perf", section: "๐Ÿ”ฅ Performance Improvements" }, + { type: "revert", section: "โฉ Reverts" }, + { type: "docs", section: "๐Ÿ“ Documentation" }, + { type: "style", section: "๐ŸŽจ Styles" }, + { type: "refactor", section: "๐Ÿง‘โ€๐Ÿ’ป Code Refactoring" }, + { type: "test", section: "โœ… Tests" }, + { type: "build", section: "๐Ÿค– Build System" }, + { type: "ci", section: "๐Ÿ” Continuous Integration" }, + ], + }, }); if (!SKIP_CHANGELOG) { addPlugin("@semantic-release/changelog", { - "changelogTitle": `# ๐Ÿ“ฆ ${owner}/${repo} changelog + changelogTitle: `# ๐Ÿ“ฆ ${owner}/${repo} changelog [![conventional commits](https://img.shields.io/badge/conventional%20commits-1.0.0-yellow.svg)](https://conventionalcommits.org) [![semantic versioning](https://img.shields.io/badge/semantic%20versioning-2.0.0-green.svg)](https://semver.org) -> All notable changes to this project will be documented in this file` +> All notable changes to this project will be documented in this file`, }); } @@ -132,85 +129,89 @@ if (!SKIP_NPM_PUBLISH) { } const actionExists = existsSync("./action.yml"); -if (actionExists) { +if (actionExists && !SKIP_ACTION_REPLACEMENT) { addPlugin("@google/semantic-release-replace-plugin", { - "replacements": [{ - "files": [ - "action.yml" - ], - "from": `image: 'docker://ghcr.io/${owner}/${repo}:.*'`, - "to": `image: 'docker://ghcr.io/${owner}/${repo}:\${nextRelease.version}'`, - "results": [{ - "file": "action.yml", - "hasChanged": true, - "numMatches": 1, - "numReplacements": 1 - }], - "countMatches": true - }] + replacements: [ + { + files: ["action.yml"], + from: `image: 'docker://ghcr.io/${owner}/${repo}:.*'`, + to: `image: 'docker://ghcr.io/${owner}/${repo}:\${nextRelease.version}'`, + results: [ + { + file: "action.yml", + hasChanged: true, + numMatches: 1, + numReplacements: 1, + }, + ], + countMatches: true, + }, + ], }); } const manifestExists = existsSync("./manifest.json"); if (manifestExists && GITHUB_REF === "refs/heads/main") { addPlugin("@google/semantic-release-replace-plugin", { - "replacements": [{ - "files": [ - "manifest.json" - ], - "from": `"version": ".*"`, - "to": `"version": "\${nextRelease.version}"`, - "results": [{ - "file": "manifest.json", - "hasChanged": true, - "numMatches": 1, - "numReplacements": 1 - }], - "countMatches": true - }] + replacements: [ + { + files: ["manifest.json"], + from: `"version": ".*"`, + to: `"version": "\${nextRelease.version}"`, + results: [ + { + file: "manifest.json", + hasChanged: true, + numMatches: 1, + numReplacements: 1, + }, + ], + countMatches: true, + }, + ], }); } const packageFilesPrefix = process.env.NPM_PACKAGE_ROOT ? `${process.env.NPM_PACKAGE_ROOT}/` : ""; addPlugin("@semantic-release/git", { - "assets": [ - "LICENSE*", - "CHANGELOG.md", - `${packageFilesPrefix}package.json`, - `${packageFilesPrefix}package-lock.json`, - `${packageFilesPrefix}npm-shrinkwrap.json`, - `${packageFilesPrefix}yarn.lock`, - `${packageFilesPrefix}pnpm-lock.yaml`, - "public/**/*", - "supabase/**/*", - "action.yml", - "manifest.json" - ], - "message": `chore(<%= nextRelease.type %>): release <%= nextRelease.version %> <%= nextRelease.channel !== null ? \`on \${nextRelease.channel} channel \` : '' %>[skip ci]\n\n<%= nextRelease.notes %>` + assets: [ + "LICENSE*", + "CHANGELOG.md", + `${packageFilesPrefix}package.json`, + `${packageFilesPrefix}package-lock.json`, + `${packageFilesPrefix}npm-shrinkwrap.json`, + `${packageFilesPrefix}yarn.lock`, + `${packageFilesPrefix}pnpm-lock.yaml`, + "public/**/*", + "supabase/**/*", + "action.yml", + "manifest.json", + ], + message: `chore(<%= nextRelease.type %>): release <%= nextRelease.version %> <%= nextRelease.channel !== null ? \`on \${nextRelease.channel} channel \` : '' %>[skip ci]\n\n<%= nextRelease.notes %>`, }); addPlugin("@semantic-release/github", { - "addReleases": "bottom", - "assets": [ + addReleases: "bottom", + assets: [ { - "path": "pack/*.tgz", - "label": "Static distribution" - } - ] + path: "pack/*.tgz", + label: "Static distribution", + }, + ], }); const dockerExists = existsSync("./Dockerfile"); if (dockerExists && !SKIP_DOCKER_PUBLISH) { addPlugin("eclass-docker-fork", { - "baseImageName": `${owner}/${repo}`, - "registries": [ + baseImageName: `${owner}/${repo}`, + registries: [ { - "url": "ghcr.io", - "imageName": `ghcr.io/${owner}/${repo}`, - "user": "GITHUB_REPOSITORY_OWNER", - "password": "GITHUB_TOKEN" - } - ] + url: "ghcr.io", + imageName: `ghcr.io/${owner}/${repo}`, + user: "GITHUB_REPOSITORY_OWNER", + password: "GITHUB_TOKEN", + }, + ], }); }