# Semantic Release bot flow ## Overview This [semantic-release](https://semantic-release.gitbook.io/) publishing flow consists of using a bot for publishing releases. Note that commits by this bot will not be signed/verfied. If this is a requirement for you, refer to [this guide](https://gist.github.com/0xernesto/fda89508b5f73463787d102e1739dc0b). This setup requires creating a Github App and adding the following Github Actions secrets to the repo it is being used in: - `NPM_TOKEN` - Refer to “Generating an NPM token” section. - `MY_RELEASER_ID` - Refer to “Creating a GitHub App” section - `MY_RELEASER_PRIVATE_KEY` - Refer to “Creating a GitHub App” section ## Generating an NPM token 1. Go to [npmjs.com](http://npmjs.com) and create an account, if necessary. 2. Click “Access Tokens” from the menu. 3. Click “Generate New Token” 4. Click “Granular Access Token” 5. Give the token a descriptive name that differentiates it from the rest of the tokens in your account, such as “My Releaser Bot” 6. Provide a description, such as “Token for My Releaser Bot” 7. Provide an expiration date, such as “12/31/2100” 8. Set permissions to “Read and write” 9. Select the package 10. Click “Generate token” 11. Copy the “Token” - ⚠️ This token will never be visible on the NPM website again. 12. Create a secret in the Github repo this will be used and name it `NPM_TOKEN` - Paste the token value from the previous step ## Create a new GitHub app We need to create an internal GitHub app to act as the release bot with very strict permissions. If the setting is not specified here, it should **NOT** be checked or filled in when creating the app. 1. Got to your Github org homepage 2. Click “Settings” 3. Click “Developer settings” 4. Click the “GitHub Apps” tab 5. Click “New GitHub App” 6. Configure the app as follows: - GitHub App name: - My Releaser (results in a my-releaser slug) - Description: - Internal bot to handle automatic releases of packages. - Homepage URL: - https://github.com/your-org - Callback URL: - https://github.com/your-org - Repository permissions: - Checks - read/write - Contents - read/write - Issues - read/write - Metadata - read - Pull requests - read/write - Secrets - read - Where can this GitHub App be installed? - Only on this account (Only allow this GitHub App to be installed on the @your-org account) 7. Click “Create GitHub App” 8. Make note of the “App ID” to reference later. 9. Click “generate a private key” - This will create a private key and trigger a download of a `.pem` file to your machine - The `.pem` must be stored securely. - If this key is lost, you will have to create a new private key in the Github app settings (you won’t have to create a new app) 10. Click the “Install App” tab and install the app in your organization - Select the repos that this internal app should have access to. - Since this is is an internal app with very limited permissions, it should be safe to give it access to all the the org’s repos. However, it probably makes sense to gradually give the app access to more repos as necessary. 11. In the repo that this bot will be used in, add the following GitHub Actions secrets - `MY_RELEASER_ID` - Paste the App ID noted earlier as the value - `MY_RELEASER_PRIVATE_KEY` - Paste the contents of the `.pem` file downloaded earlier as the value 12. If the repo has the following protections, we will have to modify the settings so that the `my-releaser` Github app can bypass one of the protections - Protections: - ☑ Require a pull request before merging - ☑ Require approvals - Modify with: - ☑ Allow specified actors to bypass the required pull requests - Search for and select `my-releaser` as an actor that can bypass this requirement - Repeat the above for every protected branch in the repo (e.g., `main`, `beta`, …) ## Github Actions Workflow The following YAML code should be placed in the projects `.github/workflows/release.yml` file of the repo you're using this bot in. Note that this file makes use of all the environment variables described in the “Overview” section, so it is crucial that they’re all defined in the Github Actions secrets of the repo you're using this bot in. The only environment variable in this file that does not need to be defined as a Github Actions secret is `GITHUB_TOKEN`. ```yaml name: release on: push: branches: - main - beta workflow_dispatch: permissions: contents: write issues: write pull-requests: write jobs: publish: runs-on: ubuntu-latest steps: - name: Generate bot app token id: generate_token uses: actions/create-github-app-token@v1 with: app-id: ${{ secrets.RELEASER_ID }} private-key: ${{ secrets.RELEASER_PRIVATE_KEY }} - name: Checkout uses: actions/checkout@v4 with: token: ${{ steps.generate_token.outputs.token }} fetch-depth: 0 persist-credentials: false - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: "20.x" - name: Get bot user ID id: bot-user-id run: | echo "user-id=$(gh api "/users/${{ steps.generate_token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" env: GH_TOKEN: ${{ steps.generate_token.outputs.token }} - name: Install dependencies run: npm install - name: Run tests run: npm run test - name: Build package run: npm run-script build env: NODE_ENV: production - name: Publish package run: npx semantic-release env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} GIT_AUTHOR_EMAIL: "${{ steps.bot-user-id.outputs.user-id }}+${{ steps.generate_token.outputs.app-slug }}[bot]@users.noreply.github.com" GIT_COMMITTER_EMAIL: "${{ steps.bot-user-id.outputs.user-id }}+${{ steps.generate_token.outputs.app-slug }}[bot]@users.noreply.github.com" ```