Skip to content

Support NPM option for release workflow & allow publishing to private GitHub repos. #4

Support NPM option for release workflow & allow publishing to private GitHub repos.

Support NPM option for release workflow & allow publishing to private GitHub repos. #4

Workflow file for this run

on:
workflow_call:
secrets:
NPM_TOKEN:
description: npm token
AWS_ACCESS_KEY_ID:
description: AWS access key id. Only required if sign = true
AWS_SECRET_ACCESS_KEY:
description: AWS secret access key. Only required if sign = true
SVC_CLI_BOT_GITHUB_TOKEN:
description: GitHub token for package publishing. Required if publishToGithubPackages is true
required: false
inputs:
tag:
required: false
description: tag used to publish to npm
default: latest
type: string
sign:
required: false
description: signs the package using sf-release if set to true
default: false
type: boolean
dryrun:
required: false
description: if true, the job will run but will not publish to npm or push to git
default: false
type: boolean
prerelease:
required: false
description: if true, it will use the version <version>-<branch>.0
type: boolean
default: false
nodeVersion:
description: version of node to use. It's better to specify latest, lts/* or lts/-1 than to hardode numbers
type: string
default: lts/*
required: false
ctc:
description: |
Use CTC. Requires environment to contain
SF_CHANGE_CASE_SFDX_AUTH_URL, SF_CHANGE_CASE_TEMPLATE_ID, SF_CHANGE_CASE_CONFIGURATION_ITEM.
Also requires a static ip runner (you can't use ubuntu-latest)
type: boolean
required: false
runsOn:
description: the runner. Only needed if you need a non-public runner (ex, for git checkout from IP restricted private repo)
default: ubuntu-latest
required: false
type: string
githubTag:
description: the github release tag that you want to publish as an npm package
required: true
type: string
package-manager:
type: string
description: "Package manager to use (npm or yarn)"
default: "yarn"
required: false
publishToGithubPackages:
type: boolean
description: "If true, publish to GitHub Packages instead of npm"
default: false
required: false
scope:
type: string
description: "Scope for the package (e.g., @organization). Required if publishToGithubPackages is true"
required: false
actions-repository:
type: string
description: "The repository owner/name to use for actions (format: owner/repo)"
default: "salesforcecli/github-workflows"
required: false
actions-ref:
type: string
description: "The branch, tag or SHA to use for actions"
default: "main"
required: false
jobs:
check-publish:
outputs:
published: ${{ steps.is-published.outputs.published }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.githubTag }}
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.nodeVersion }}
registry-url: ${{ inputs.publishToGithubPackages && 'https://npm.pkg.github.com' || '' }}
scope: ${{ inputs.scope }}
- name: Is published
id: is-published
run: |
if [ "$INPUTS_PUBLISH_TO_GITHUB_PACKAGES" = "true" ]; then
# For GitHub Packages, check if the package exists in the registry
RESPONSE=$(npm view $INPUTS_SCOPE/$GITHUB_REPOSITORY_NAME@$INPUTS_GITHUB_TAG version --json --silent || echo "Not published")
else
# For npm, check if the package exists in the npm registry
RESPONSE=$(npm view .@$INPUTS_GITHUB_TAG version --json --silent || echo "Not published")
fi
# The response is wrapped in double quotes, so we need to compare it with (escaped) quotes
if [ "$RESPONSE" = "\"$INPUTS_GITHUB_TAG\"" ]; then
echo "published=true" >> "$GITHUB_OUTPUT"
else
echo "published=false" >> "$GITHUB_OUTPUT"
fi
env:
INPUTS_GITHUB_TAG: ${{ inputs.githubTag }}
INPUTS_PUBLISH_TO_GITHUB_PACKAGES: ${{ inputs.publishToGithubPackages }}
INPUTS_SCOPE: ${{ inputs.scope }}
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
NODE_AUTH_TOKEN: ${{ inputs.publishToGithubPackages && secrets.SVC_CLI_BOT_GITHUB_TOKEN || secrets.NPM_TOKEN }}
- run: echo "[INFO] Is package published:\ $STEPS_IS_PUBLISHED_PUBLISHED"
env:
STEPS_IS_PUBLISHED_PUBLISHED: ${{ steps.is-published.outputs.published }}
- name: Fail if published
if: steps.is-published.outputs.published == 'true'
uses: actions/github-script@v7
with:
script: |
const message = 'The version \'' + process.env.INPUTS_GITHUB_TAG + '\' has already been published to ' +
(process.env.INPUTS_PUBLISH_TO_GITHUB_PACKAGES === 'true' ? 'GitHub Packages' : 'npm');
core.setFailed(message);
env:
INPUTS_GITHUB_TAG: ${{ inputs.githubTag }}
INPUTS_PUBLISH_TO_GITHUB_PACKAGES: ${{ inputs.publishToGithubPackages }}
ctc-open:
needs: [check-publish]
if: inputs.ctc && needs.check-publish.outputs.published == 'false'
uses: ${{ inputs.actions-repository }}/.github/workflows/ctcOpen.yml@${{ inputs.actions-ref }}

Check failure on line 142 in .github/workflows/npmPublish.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/npmPublish.yml

Invalid workflow file

invalid value workflow reference: version cannot have whitespace: ${{ inputs.actions-ref }}
secrets: inherit
with:
actions-repository: ${{ inputs.actions-repository }}
actions-ref: ${{ inputs.actions-ref }}
npm-publish:
needs: [check-publish, ctc-open]
if: ${{ always() && needs.check-publish.outputs.published == 'false' && (!inputs.ctc || (inputs.ctc && needs.ctc-open.outputs.changeCaseId)) }}
runs-on: ${{ inputs.runsOn }}
permissions:
contents: read
packages: write
steps:
- name: Validate inputs
if: inputs.publishToGithubPackages == 'true'
run: |
if [ -z "$INPUTS_SCOPE" ]; then
echo "Error: scope is required when publishing to GitHub Packages"
exit 1
fi
env:
INPUTS_SCOPE: ${{ inputs.scope }}
- uses: actions/checkout@v4
with:
ref: ${{ inputs.githubTag }}
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.nodeVersion }}
cache: ${{ inputs.package-manager }}
registry-url: ${{ inputs.publishToGithubPackages && 'https://npm.pkg.github.com' || '' }}
scope: ${{ inputs.scope }}
- uses: ${{ inputs.actions-repository }}/.github/actions/yarnInstallWithRetries@${{ inputs.actions-ref }}
if: inputs.package-manager == 'yarn'
- name: npm install
if: inputs.package-manager == 'npm'
run: npm ci
- name: Build
run: ${{ inputs.package-manager }} build
- run: npm install -g @salesforce/plugin-release-management
- name: NPM Release
run: |
sf-release npm:package:release \
--githubtag "$INPUTS_GITHUB_TAG" \
--npmtag "$INPUTS_TAG" \
--no-install \
${{ inputs.dryrun && '--dryrun' || '' }} \
${{ inputs.prerelease && format('--prerelease {0}', github.ref_name) || '' }} \
${{ inputs.sign && '--sign' || '' }}
env:
INPUTS_GITHUB_TAG: ${{ inputs.githubTag }}
INPUTS_TAG: ${{ inputs.tag }}
NPM_TOKEN: ${{ inputs.publishToGithubPackages && secrets.SVC_CLI_BOT_GITHUB_TOKEN || secrets.NPM_TOKEN }}
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
ctcCloseSuccess:
needs: [ctc-open, npm-publish]
if: needs.ctc-open.result == 'success' && needs.npm-publish.result == 'success' && needs.ctc-open.outputs.changeCaseId
uses: ${{ inputs.actions-repository }}/.github/workflows/ctcClose.yml@${{ inputs.actions-ref }}
secrets: inherit
with:
changeCaseId: ${{needs.ctc-open.outputs.changeCaseId}}
actions-repository: ${{ inputs.actions-repository }}
actions-ref: ${{ inputs.actions-ref }}
ctcCloseFail:
needs: [ctc-open, npm-publish]
if: always() && inputs.ctc && needs.ctc-open.outputs.changeCaseId && (needs.ctc-open.result != 'success' || needs.npm-publish.result != 'success')
uses: ${{ inputs.actions-repository }}/.github/workflows/ctcClose.yml@${{ inputs.actions-ref }}
secrets: inherit
with:
changeCaseId: ${{ needs.ctc-open.outputs.changeCaseId }}
status: Not Implemented
actions-repository: ${{ inputs.actions-repository }}
actions-ref: ${{ inputs.actions-ref }}