Publish to NPM #198
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: Publish to NPM | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: Git ref to publish (branch, tag, or commit SHA) | |
| required: true | |
| type: string | |
| tag: | |
| description: NPM dist-tag | |
| required: true | |
| type: choice | |
| default: latest | |
| options: | |
| - latest | |
| - beta | |
| - runtime | |
| allow_unmerged_latest: | |
| description: "Allow 'latest' from a ref that is not contained in master (deliberate releases only)" | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| id-token: write # Required for OIDC | |
| contents: read | |
| jobs: | |
| publish_to_npm: | |
| name: Publish to NPM | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ inputs.ref }} | |
| # The master containment check below needs real history, not a shallow clone. | |
| fetch-depth: 0 | |
| # 'latest' is what plain `npm install -g apify-cli` resolves to, so it must not come from a | |
| # side channel branch by accident. Side channels (beta, runtime) are opt-in and unrestricted. | |
| - name: Check the ref is in master before publishing 'latest' | |
| if: ${{ inputs.tag == 'latest' }} | |
| env: | |
| ALLOW_UNMERGED_LATEST: ${{ inputs.allow_unmerged_latest }} | |
| run: | | |
| if [ "$ALLOW_UNMERGED_LATEST" = "true" ]; then | |
| echo "allow_unmerged_latest is set, skipping the master containment check." | |
| exit 0 | |
| fi | |
| git fetch --no-tags origin master | |
| if ! git merge-base --is-ancestor HEAD origin/master; then | |
| echo "::error::Refusing to publish the 'latest' dist-tag from $(git rev-parse HEAD) - it is not contained in origin/master. Publish a side channel (tag 'beta' or 'runtime') instead, or re-run with allow_unmerged_latest to release from another branch on purpose." | |
| exit 1 | |
| fi | |
| - name: Use Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 24 | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Install pnpm and dependencies | |
| uses: apify/actions/pnpm-install@v1.3.1 | |
| - name: Check version consistency and bump pre-release version (beta only) | |
| if: ${{ inputs.tag == 'beta' }} | |
| run: pnpm exec tsx ./.github/scripts/before-prerelease.ts --tag beta | |
| # Side channels are published off long-lived branches whose package.json still carries the | |
| # last released version, so the base version is moved forward instead of failing the build. | |
| - name: Bump pre-release version (side channels) | |
| if: ${{ inputs.tag != 'beta' && inputs.tag != 'latest' }} | |
| run: pnpm exec tsx ./.github/scripts/before-prerelease.ts --tag "${{ inputs.tag }}" --bump-base-if-published | |
| - name: Build module | |
| run: pnpm run build | |
| # The preinstall script enforces pnpm for local development, but breaks | |
| # consumers installing with npm (e.g. npm install -g apify-cli) because | |
| # npm runs preinstall for top-level/global installs. | |
| - name: Remove preinstall guard | |
| run: jq 'del(.scripts.preinstall)' package.json > tmp.json && mv tmp.json package.json | |
| - name: Publish to NPM | |
| run: pnpm publish --provenance --access public --no-git-checks --tag ${{ inputs.tag }} | |
| - name: Report what was published | |
| run: | | |
| echo "### Published \`apify-cli@$(jq -r .version package.json)\` under the \`${{ inputs.tag }}\` dist-tag" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Install it with \`npm install -g apify-cli@${{ inputs.tag }}\`" >> $GITHUB_STEP_SUMMARY |