backport: internal: streamline release process (#4615) (#4626) #22
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 | |
| on: | |
| push: | |
| branches: | |
| - 16.x.x | |
| permissions: {} | |
| jobs: | |
| check-publish: | |
| name: Check for publish need and prepare artifacts | |
| # Keep this guard on every job for defense-in-depth in case job dependencies are refactored. | |
| if: ${{ !github.event.repository.fork && github.repository == 'graphql/graphql-js' && github.ref_name == '16.x.x' }} | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_publish: ${{ steps.release_metadata.outputs.should_publish }} | |
| tag: ${{ steps.release_metadata.outputs.tag }} | |
| dist_tag: ${{ steps.release_metadata.outputs.dist_tag }} | |
| prerelease: ${{ steps.release_metadata.outputs.prerelease }} | |
| tarball_name: ${{ steps.release_metadata.outputs.tarball_name }} | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref_name }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read # for actions/checkout | |
| steps: | |
| - name: Checkout repo | |
| uses: actions/checkout@v4 | |
| with: | |
| # Keep checkout fast: we should only need to scroll back a few | |
| # commits for release notes. If the release commit is older than | |
| # this depth, release:metadata will emit empty release notes. | |
| fetch-depth: 10 | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| cache: npm | |
| node-version-file: '.node-version' | |
| - name: Install Dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Read release metadata | |
| id: release_metadata | |
| run: | | |
| release_metadata_json="$(npm run --silent release:metadata)" | |
| jq -r ' | |
| "version=\(.version)", | |
| "tag=\(.tag)", | |
| "dist_tag=\(.distTag)", | |
| "prerelease=\(.prerelease)", | |
| "package_spec=\(.packageSpec)", | |
| "tarball_name=\(.tarballName)", | |
| "should_publish=\(.shouldPublish)" | |
| ' <<< "${release_metadata_json}" >> "${GITHUB_OUTPUT}" | |
| jq -r '.releaseNotes' <<< "${release_metadata_json}" > ./release-notes.md | |
| - name: Log publish decision | |
| run: | | |
| if [ "${{ steps.release_metadata.outputs.should_publish }}" = "true" ]; then | |
| echo "${{ steps.release_metadata.outputs.package_spec }} is not published yet." | |
| else | |
| echo "${{ steps.release_metadata.outputs.package_spec }} is already published." | |
| fi | |
| - name: Build NPM package | |
| if: steps.release_metadata.outputs.should_publish == 'true' | |
| run: npm run build:npm | |
| - name: Pack npmDist package | |
| if: steps.release_metadata.outputs.should_publish == 'true' | |
| run: npm pack ./npmDist --pack-destination . > /dev/null | |
| - name: Upload npm package tarball | |
| if: steps.release_metadata.outputs.should_publish == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: npmDist-tarball | |
| path: ./${{ steps.release_metadata.outputs.tarball_name }} | |
| - name: Upload release notes | |
| if: steps.release_metadata.outputs.should_publish == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-notes | |
| path: ./release-notes.md | |
| publish-npm: | |
| name: Publish npm package | |
| needs: check-publish | |
| # Keep this guard on every job for defense-in-depth in case job dependencies are refactored. | |
| if: ${{ !github.event.repository.fork && github.repository == 'graphql/graphql-js' && github.ref_name == '16.x.x' && needs.check-publish.outputs.should_publish == 'true' && needs.check-publish.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| environment: release | |
| permissions: | |
| contents: read # keep token scopes minimal | |
| id-token: write # for npm trusted publishing via OIDC | |
| steps: | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| # npm trusted publishing requires a newer Node/npm line than 16.x.x | |
| # branch runtime constraints, so pin only this job to Node 24. | |
| node-version: 24 | |
| - name: Download npmDist package | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: npmDist-tarball | |
| path: ./artifacts | |
| - name: Publish npm package | |
| run: | | |
| if [ -n "${{ needs.check-publish.outputs.dist_tag }}" ]; then | |
| npm publish --provenance --tag "${{ needs.check-publish.outputs.dist_tag }}" "./artifacts/${{ needs.check-publish.outputs.tarball_name }}" | |
| else | |
| npm publish --provenance "./artifacts/${{ needs.check-publish.outputs.tarball_name }}" | |
| fi | |
| create-release: | |
| name: Create release | |
| needs: check-publish | |
| # Keep this guard on every job for defense-in-depth in case job dependencies are refactored. | |
| if: ${{ !github.event.repository.fork && github.repository == 'graphql/graphql-js' && github.ref_name == '16.x.x' && needs.check-publish.outputs.should_publish == 'true' && needs.check-publish.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| environment: release | |
| permissions: | |
| contents: write # for creating GitHub release | |
| steps: | |
| - name: Checkout repo | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Download release notes | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-notes | |
| path: ./artifacts | |
| - name: Create release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| tag="${{ needs.check-publish.outputs.tag }}" | |
| if gh release view "${tag}" > /dev/null 2>&1; then | |
| echo "GitHub release ${tag} already exists. Skipping release creation." | |
| exit 0 | |
| fi | |
| if git ls-remote --exit-code --tags origin "refs/tags/${tag}" > /dev/null; then | |
| echo "Tag ${tag} already exists on origin." | |
| else | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag -a "${tag}" "${GITHUB_SHA}" -m "${tag}" | |
| gh auth setup-git | |
| git push origin "refs/tags/${tag}" | |
| echo "Created annotated tag ${tag} at ${GITHUB_SHA}." | |
| fi | |
| release_notes_file="./artifacts/release-notes.md" | |
| if [ "${{ needs.check-publish.outputs.prerelease }}" = "true" ]; then | |
| gh release create "${tag}" \ | |
| --verify-tag \ | |
| --title "${tag}" \ | |
| --notes-file "${release_notes_file}" \ | |
| --prerelease | |
| else | |
| gh release create "${tag}" \ | |
| --verify-tag \ | |
| --title "${tag}" \ | |
| --notes-file "${release_notes_file}" | |
| fi |