Release Package #15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Package | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| package: | |
| description: "Which package to release" | |
| required: true | |
| type: choice | |
| options: | |
| - compact-builder | |
| - compact-cli | |
| - compact-simulator | |
| version_bump: | |
| description: "Version bump type (pre* strategies are beta-only)" | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| - prerelease | |
| - prepatch | |
| - preminor | |
| - premajor | |
| jobs: | |
| release: | |
| name: Open release PR for ${{ inputs.package }} | |
| runs-on: ubuntu-24.04 | |
| environment: compact-npm-prod # Requires approval before opening the release PR | |
| permissions: | |
| contents: write # create the release branch | |
| pull-requests: write # open the PR + enable auto-merge | |
| steps: | |
| # Prerelease versions carry the `beta` npm dist-tag and stable versions | |
| # carry `latest`. Pinning each strategy to its branch keeps a beta out of | |
| # main's history and a stable out of beta's. | |
| - name: Validate bump strategy for this branch | |
| env: | |
| BRANCH: ${{ github.ref_name }} | |
| BUMP: ${{ inputs.version_bump }} | |
| run: | | |
| case "$BUMP" in | |
| prerelease|prepatch|preminor|premajor) | |
| if [[ "$BRANCH" != "beta" ]]; then | |
| echo "::error::$BUMP is beta-only, but this run is on '$BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| patch|minor|major) | |
| if [[ "$BRANCH" != "main" ]]; then | |
| echo "::error::$BUMP is main-only, but this run is on '$BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| *) | |
| echo "::error::unknown bump strategy: $BUMP" | |
| exit 1 | |
| ;; | |
| esac | |
| - name: Get github app token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| id: gh-app-token | |
| with: | |
| app-id: ${{ vars.GH_APP_ID }} | |
| private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} | |
| - name: Check out code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ steps.gh-app-token.outputs.token }} | |
| - name: Set package directory | |
| id: pkg | |
| run: | | |
| case "${{ inputs.package }}" in | |
| "compact-builder") | |
| echo "dir=builder" >> $GITHUB_OUTPUT | |
| ;; | |
| "compact-cli") | |
| echo "dir=cli" >> $GITHUB_OUTPUT | |
| ;; | |
| "compact-simulator") | |
| echo "dir=simulator" >> $GITHUB_OUTPUT | |
| ;; | |
| esac | |
| - name: Setup Environment | |
| uses: ./.github/actions/setup | |
| - name: Run tests for package | |
| run: yarn test --filter=@openzeppelin/${{ inputs.package }} | |
| - name: Build package | |
| run: yarn build --filter=@openzeppelin/${{ inputs.package }} | |
| - name: Bump version | |
| id: version | |
| run: | | |
| cd packages/${{ steps.pkg.outputs.dir }} | |
| yarn version ${{ inputs.version_bump }} | |
| NEW_VERSION=$(node -p "require('./package.json').version") | |
| # Yarn has no --preid, so a pre* strategy off a stable version yields a | |
| # bare counter (0.3.1 -> 0.3.2-0). Relabel it once; from there yarn | |
| # carries the identifier forward (0.3.2-beta.0 -> 0.3.2-beta.1). | |
| if [[ "$NEW_VERSION" =~ -[0-9]+$ ]]; then | |
| yarn version "${NEW_VERSION%-*}-beta.0" | |
| NEW_VERSION=$(node -p "require('./package.json').version") | |
| fi | |
| if [[ "$NEW_VERSION" == *-beta.* ]]; then | |
| DIST_TAG=beta | |
| else | |
| DIST_TAG=latest | |
| fi | |
| { | |
| echo "new=$NEW_VERSION" | |
| echo "branch=release/${{ inputs.package }}-v$NEW_VERSION" | |
| echo "dist_tag=$DIST_TAG" | |
| } >> $GITHUB_OUTPUT | |
| { | |
| echo "### Release Summary" | |
| echo "- Package: ${{ inputs.package }}" | |
| echo "- New version: $NEW_VERSION" | |
| echo "- Bump type: ${{ inputs.version_bump }}" | |
| echo "- npm dist-tag: $DIST_TAG" | |
| } >> $GITHUB_STEP_SUMMARY | |
| - name: Verify package contents | |
| run: | | |
| cd packages/${{ steps.pkg.outputs.dir }} | |
| yarn pack --dry-run | |
| # Branch protection blocks direct pushes to main, so route the version bump | |
| # through a PR: create branch → signed bot commit → open PR → auto-merge. | |
| - name: Create release branch | |
| env: | |
| GH_TOKEN: ${{ steps.gh-app-token.outputs.token }} | |
| BRANCH: ${{ steps.version.outputs.branch }} | |
| run: | | |
| if gh api "/repos/${{ github.repository }}/git/refs/heads/$BRANCH" >/dev/null 2>&1; then | |
| echo "branch $BRANCH already exists, reusing it" | |
| else | |
| SHA=$(gh api "/repos/${{ github.repository }}/git/refs/heads/${{ github.ref_name }}" -q .object.sha) | |
| gh api --method POST "/repos/${{ github.repository }}/git/refs" \ | |
| -f ref="refs/heads/$BRANCH" \ | |
| -f sha="$SHA" | |
| fi | |
| - name: Commit version bump | |
| uses: iarekylew00t/verified-bot-commit@33985d44b7719dcaf0b854a0f4b0caad9bdc5b86 # v2.3.3 | |
| with: | |
| message: "release: ${{ inputs.package }} v${{ steps.version.outputs.new }}" | |
| token: ${{ steps.gh-app-token.outputs.token }} | |
| ref: ${{ steps.version.outputs.branch }} | |
| files: | | |
| packages/${{ steps.pkg.outputs.dir }}/package.json | |
| - name: Ensure release label exists | |
| env: | |
| GH_TOKEN: ${{ steps.gh-app-token.outputs.token }} | |
| run: | | |
| gh label create release \ | |
| --description "Automated release PR" \ | |
| --color ededed \ | |
| --force | |
| - name: Open release PR | |
| id: open-pr | |
| env: | |
| GH_TOKEN: ${{ steps.gh-app-token.outputs.token }} | |
| BRANCH: ${{ steps.version.outputs.branch }} | |
| run: | | |
| cat > /tmp/pr-body.md <<EOF | |
| Automated release PR for **${{ inputs.package }}** v${{ steps.version.outputs.new }} (${{ inputs.version_bump }} bump). | |
| Publishes to npm under the \`${{ steps.version.outputs.dist_tag }}\` dist-tag. | |
| This PR was opened by the release workflow. Once required checks pass (semgrep, CodeQL, code-owner review), it will auto-merge. Merging will trigger the publish workflow, which tags the release and publishes to npm. | |
| EOF | |
| PR_URL=$(gh pr create \ | |
| --base "${{ github.ref_name }}" \ | |
| --head "$BRANCH" \ | |
| --title "release: ${{ inputs.package }} v${{ steps.version.outputs.new }}" \ | |
| --label release \ | |
| --body-file /tmp/pr-body.md) | |
| echo "url=$PR_URL" >> $GITHUB_OUTPUT | |
| echo "- PR: $PR_URL" >> $GITHUB_STEP_SUMMARY | |
| # If this step fails with "auto-merge is not allowed", enable it under | |
| # Settings → General → "Allow auto-merge", then re-run the workflow. | |
| - name: Enable auto-merge | |
| env: | |
| GH_TOKEN: ${{ steps.gh-app-token.outputs.token }} | |
| run: gh pr merge "${{ steps.open-pr.outputs.url }}" --auto --squash |