-
Notifications
You must be signed in to change notification settings - Fork 1.7k
ci: automate the v-next release process using changesets #6565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
890b5c3
c45cf55
32a8235
1b01042
5764c24
79e71bd
a95cb21
3b67142
43e9c5d
0ab8274
43d4625
6ab7aa3
7545b1b
269ef94
2c99e91
1384c36
90febd1
5366fbf
d0382d5
4d9a915
5fe4b0d
8d0921f
af53084
86d3f40
3c333bd
a3f98e5
debec91
644d4ef
6805975
71e94b4
43693af
7b58bd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,207 @@ | ||
| name: Release | ||
|
|
||
| on: | ||
| # TODO: When a release PR is merged we should run a merge_group check to ensure: | ||
| # 1. The release PR is the only one in the merge group | ||
| # 2. The release PR is up-to-date with the target branch | ||
| # i.e. no other PR has been merged since the release PR was added to the merge queue | ||
|
galargh marked this conversation as resolved.
Outdated
|
||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - main | ||
| - v-next | ||
|
|
||
| defaults: | ||
| run: | ||
| shell: bash | ||
|
|
||
| jobs: | ||
| release: | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| contents: write # This allows us to push to the repository and create GitHub releases | ||
| pull-requests: write # This allows us to create pull requests | ||
| steps: | ||
| - name: Checkout Repo | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits | ||
| fetch-depth: 0 | ||
|
|
||
| - uses: ./.github/actions/setup-env | ||
| - name: Set up the environment | ||
| uses: ./.github/actions/setup-env | ||
|
|
||
| - name: Install Dependencies | ||
| run: pnpm install --frozen-lockfile --prefer-offline | ||
|
|
||
| - name: Create Release Pull Request | ||
| id: pr | ||
| env: | ||
| # NOTE: If we use the GITHUB_TOKEN to create the release PR, the checks will not be triggered automatically | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
|
galargh marked this conversation as resolved.
Outdated
|
||
| uses: changesets/action@v1 | ||
| with: | ||
| version: pnpm run version | ||
|
|
||
| - name: Build All Packages | ||
| if: steps.pr.outputs.hasChangesets == 'false' | ||
| run: pnpm run --recursive -no-bail --filter './v-next/**' --if-present build | ||
|
|
||
| - name: Publish All Packages (dry-run) | ||
| if: steps.pr.outputs.hasChangesets == 'false' | ||
| run: pnpm publish --filter "./v-next/**" -r --no-git-checks --tag next --access public --dry-run | ||
|
|
||
| # NOTE: When running publish on an already published package we expect it to succeed but not to release anything and not include + hardhat@ in the output. | ||
| # If it does, however, include + hardhat@ in the output, it's OK, because we'll just update the release without moving the release tag forward. | ||
|
galargh marked this conversation as resolved.
Outdated
|
||
| - name: Publish All Packages | ||
| id: publish | ||
| if: steps.pr.outputs.hasChangesets == 'false' | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} | ||
| NPM_CONFIG_PROVENANCE: true | ||
| run: | | ||
| echo "stdout<<EOF" >> $GITHUB_OUTPUT | ||
| pnpm publish --filter "./v-next/**" -r --no-git-checks --tag next --access public | tee -a $GITHUB_OUTPUT | ||
| echo "EOF" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Check if hardhat was published | ||
| id: hardhat | ||
| if: steps.pr.outputs.hasChangesets == 'false' | ||
| env: | ||
| STDOUT: ${{ steps.publish.outputs.stdout }} | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const lines = process.env.STDOUT.split('\n') | ||
|
|
||
| core.info('Checking if Hardhat was published') | ||
|
|
||
| const line = lines.find(line => line.startsWith('+ hardhat@')) | ||
|
|
||
| if (line === undefined) { | ||
| core.info('Hardhat was not published') | ||
| core.setOutput('version', '') | ||
| process.exit(0) | ||
| } | ||
|
|
||
| const version = line.split('@')[1] | ||
| core.info(`Hardhat was published with version ${version}`) | ||
| core.setOutput('version', version) | ||
|
|
||
| - name: Check the version of the published package | ||
| id: version | ||
| if: steps.hardhat.outputs.version != '' | ||
| env: | ||
| VERSION: ${{ steps.hardhat.outputs.version }} | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const version = process.env.VERSION | ||
|
|
||
| core.info('Checking if Hardhat was published as a prerelease') | ||
|
|
||
| // NOTE: This check would mark non-prerelease versions with - in the build tag as prereleases | ||
|
galargh marked this conversation as resolved.
Outdated
|
||
| const prerelease = version.includes('-') | ||
| if (prerelease) { | ||
| core.info('Hardhat was published as a prerelease') | ||
| core.setOutput('prerelease', true) | ||
| } else { | ||
| core.info('Hardhat was not published as a prerelease') | ||
| core.setOutput('prerelease', false) | ||
| } | ||
|
|
||
| core.info('Checking if this is the latest version') | ||
|
|
||
| if (prerelease) { | ||
| core.info('This is a prerelease, so this is not the latest version') | ||
| core.setOutput('latest', false) | ||
| process.exit(0) | ||
| } | ||
|
|
||
| try { | ||
| const { data: release } = await github.rest.repos.getLatestRelease(context.repo) | ||
|
|
||
| const latestVersion = release.tag_name.split('@')[1] | ||
| core.info(`Current latest version is ${latestVersion}`) | ||
|
|
||
| const [major, minor, patch] = version.split('.') | ||
| const [latestMajor, latestMinor, latestPatch] = latestVersion.split('.') | ||
|
|
||
| if (parseInt(major, 10) > parseInt(latestMajor, 10) || | ||
| parseInt(minor, 10) > parseInt(latestMinor, 10) || | ||
| parseInt(patch, 10) > parseInt(latestPatch, 10)) { | ||
| core.info('This is a new latest version') | ||
| core.setOutput('latest', true) | ||
| } else { | ||
| core.info('This is not a new latest version') | ||
| core.setOutput('latest', false) | ||
| } | ||
| } catch (error) { | ||
| if (error.status === 404) { | ||
| core.info('No existing latest release found, so this is the latest version') | ||
| core.setOutput('latest', true) | ||
| process.exit(0) | ||
| } | ||
| throw error | ||
| } | ||
|
|
||
| - name: Find the relevant changelog entry | ||
| id: changelog | ||
| if: steps.hardhat.outputs.version != '' | ||
| env: | ||
| VERSION: ${{ steps.hardhat.outputs.version }} | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const fs = require('fs') | ||
|
|
||
| const changelog = fs.readFileSync('./v-next/hardhat/CHANGELOG.md').toString() | ||
| core.debug(`Changelog: ${changelog}`) | ||
|
|
||
| core.info('Parsing changelog...') | ||
| const lines = changelog.split('\n') | ||
| const headerIndex = lines.findIndex((line) => line == `## ${process.env.VERSION}`) | ||
|
|
||
| if (headerIndex == -1) { | ||
| core.error(`Changelog entry for version ${process.env.VERSION} not found in ./v-next/hardhat/CHANGELOG.md`) | ||
| process.exit(1) | ||
| } | ||
|
|
||
| const entryLines = []; | ||
|
|
||
| for (const line of lines.slice(headerIndex + 1)) { | ||
| if (line.startsWith('## ')) { | ||
| break | ||
| } | ||
| entryLines.push(line) | ||
| } | ||
|
|
||
| const entry = entryLines.join('\n').trim() | ||
|
|
||
| core.debug(`Entry: ${entry}`) | ||
| core.setOutput('entry', entry) | ||
|
|
||
| - name: Create GitHub Release | ||
| if: steps.hardhat.outputs.version != '' | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
| # NOTE: The action updates the release if it already exists | ||
|
galargh marked this conversation as resolved.
Outdated
|
||
| uses: galargh/action-gh-release@571276229e7c9e6ea18f99bad24122a4c3ec813f # https://github.com/galargh/action-gh-release/pull/1 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we able to push this to Nomic to keep us self-contained?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we should be able to use the https://github.com/softprops/action-gh-release version of the action instead of my fork now as both my PRs got merged there. I would leave it as a TODO for later though as I would like to carefully check what other things they introduced in their action.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah. What is it that drives pulling in an external task here? Is the GitHub API around releases just really cumbersome here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I think about it, we should be able to use the API directly in our case. This action is great for a little more advanced setups. Especially those where a draft gets updated over and over again. However, in our setup, we only ever create the draft once and that's it. I'm going to update it to use the GitHub API directly. Thanks for pointing this out. I might not be able to finish it before our meeting though.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool lets do that as a follow up PR. |
||
| with: | ||
| draft: false | ||
| tag_name: hardhat@${{ steps.hardhat.outputs.version }} | ||
| generate_release_notes: false | ||
| target_commitish: ${{ github.sha }} | ||
| make_latest: ${{ steps.version.outputs.latest == 'true' }} | ||
| prerelease: ${{ steps.version.outputs.prerelease == 'true' }} | ||
| body: | | ||
| # ${{ steps.hardhat.outputs.version }} | ||
|
|
||
| ## Changes | ||
|
|
||
| ${{ steps.changelog.outputs.entry }} | ||
|
|
||
| --- | ||
| > 💡 **The Nomic Foundation is hiring! Check [our open positions](https://www.nomic.foundation/jobs).** | ||
| --- | ||
| token: ${{ github.token }} | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we ever wanted to stop releasing all the packages together, we could group the ones linked through peer dependency relations here instead.