Skip to content

ci: publish npm package from release asset #82

ci: publish npm package from release asset

ci: publish npm package from release asset #82

name: 🌍 Release

Check failure on line 1 in .github/workflows/on-release-published.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/on-release-published.yml

Invalid workflow file

(Line: 100, Col: 24): Unrecognized named-value: 'env'. Located at position 1 within expression: env.RELEASE_TAG
run-name: Release ${{ github.event.release.tag_name || inputs.version || github.ref_name }}
on:
workflow_dispatch:
inputs:
version:
description: 'Release tag to publish, for example 0.74.0'
required: false
type: string
npm_only:
description: 'Only publish the audited npm tarball for the selected release'
required: false
default: false
type: boolean
release:
types: [published]
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: release-publish-${{ github.event.release.tag_name || inputs.version || github.ref_name }}
cancel-in-progress: false
env:
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.version || github.ref_name }}
jobs:
deploy-website:
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.npm_only }}
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout released ref
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: website/package-lock.json
- name: Install website dependencies
run: |
cd website
npm ci
- name: Build website
env:
FSCRIPT_DOCS_LAST_VERSION: ${{ env.RELEASE_TAG || 'current' }}
run: |
cd website
npm run build
- name: Configure GitHub Pages
uses: actions/configure-pages@v5
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v4
with:
path: website/build
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
release-nuget:
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.npm_only }}
runs-on: ubuntu-latest
steps:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.201
- name: Download GitHub release artifacts
uses: robinraju/release-downloader@v1.11
with:
tag: ${{ env.RELEASE_TAG }}
fileName: '*.nupkg'
- name: Push packages to NuGet
run: |
shopt -s nullglob
for pkg in ./*.nupkg; do
dotnet nuget push "$pkg" --skip-duplicate --api-key "${{ secrets.NUGET_KEY }}" --source https://api.nuget.org/v3/index.json
done
release-npm:
runs-on: ubuntu-latest
env:
RELEASE_VERSION: ${{ env.RELEASE_TAG }}
PACKAGE_NAME: '@magnusopera/fscript'
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
- name: Download npm package artifact
uses: robinraju/release-downloader@v1.11
with:
tag: ${{ env.RELEASE_TAG }}
fileName: '*.tgz'
- name: Publish npm package
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_KEY }}
run: |
if [[ -z "${NODE_AUTH_TOKEN:-}" ]]; then
echo "::error::NPM_KEY secret is not configured."
exit 1
fi
shopt -s nullglob
packages=(./*.tgz)
if [[ "${#packages[@]}" -ne 1 ]]; then
echo "::error::Expected exactly one audited npm .tgz release asset, found ${#packages[@]}."
exit 1
fi
if npm view "${PACKAGE_NAME}@${RELEASE_VERSION}" version >/dev/null 2>&1; then
echo "${PACKAGE_NAME}@${RELEASE_VERSION} is already published; skipping."
exit 0
fi
npm publish "${packages[0]}" --access public --provenance
publish-vscode-marketplace:
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.npm_only }}
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Download VSIX artifact
uses: robinraju/release-downloader@v1.11
with:
tag: ${{ env.RELEASE_TAG }}
fileName: '*.vsix'
- name: Install VS Code publishing tool
run: npm install -g @vscode/vsce@3.5
- name: Publish to VS Code Marketplace
shell: bash
env:
VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }}
run: ./.github/scripts/publish-vscode-marketplace.sh
publish-open-vsx:
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.npm_only }}
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Download VSIX artifact
uses: robinraju/release-downloader@v1.11
with:
tag: ${{ env.RELEASE_TAG }}
fileName: '*.vsix'
- name: Install Open VSX publishing tool
run: npm install -g ovsx@0.9
- name: Publish to Open VSX
shell: bash
env:
OPEN_VSX_TOKEN: ${{ secrets.OPEN_VSX_TOKEN }}
run: ./.github/scripts/publish-open-vsx.sh
sign-and-notarize:
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.npm_only }}
runs-on: macos-latest
steps:
- name: Download unsigned macOS artifacts
uses: robinraju/release-downloader@v1.11
with:
tag: ${{ env.RELEASE_TAG }}
fileName: 'fscript-*-darwin-unsigned.zip'
- name: Extract binaries
run: |
mkdir -p .out/darwin
unzip -d .out/darwin fscript-${{ env.RELEASE_TAG }}-darwin-unsigned.zip
test -f .out/darwin/entitlements.plist
- name: Add cert to keychain
uses: apple-actions/import-codesign-certs@v3
with:
p12-file-base64: ${{ secrets.MAC_CERT_BASE64 }}
p12-password: ${{ secrets.MAC_CERT_PASSWORD }}
- name: Sign binaries
run: |
codesign --force --timestamp --sign "Developer ID Application: Magnus Opera (${{ secrets.MAC_DEV_TEAM_ID }})" .out/darwin/arm64/fscript --options=runtime --no-strict --entitlements .out/darwin/entitlements.plist --identifier "${{ secrets.MAC_CERT_BUNDLE_ID }}.arm64"
(cd .out/darwin/arm64; zip ../fscript-${{ env.RELEASE_TAG }}-darwin-arm64.zip ./*)
- name: Notarize arm64
uses: GuillaumeFalourd/notary-tools@v1
timeout-minutes: 10
with:
product_path: '.out/darwin/fscript-${{ env.RELEASE_TAG }}-darwin-arm64.zip'
apple_id: ${{ secrets.MAC_DEV_LOGIN }}
password: ${{ secrets.MAC_DEV_PASSWORD }}
team_id: ${{ secrets.MAC_DEV_TEAM_ID }}
xcode_path: '/Applications/Xcode_16.4.app'
staple: false
- name: Upload signed macOS artifacts
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.RELEASE_TAG }}
files: |
.out/darwin/fscript-${{ env.RELEASE_TAG }}-darwin-arm64.zip
- name: Remove unsigned macOS artifact
continue-on-error: true
uses: actions/github-script@v7
with:
script: |
try {
const tag = process.env.RELEASE_TAG;
const unsignedName = `fscript-${tag}-darwin-unsigned.zip`;
const { data: release } = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag,
});
const asset = release.assets.find(a => a.name === unsignedName);
if (!asset) {
core.info(`Unsigned artifact not found: ${unsignedName}`);
return;
}
await github.rest.repos.deleteReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
asset_id: asset.id,
});
core.info(`Deleted unsigned artifact: ${unsignedName}`);
} catch (error) {
core.warning(`Best-effort cleanup failed: ${error?.message ?? error}`);
}
update-homebrew-tap:
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.npm_only }}
uses: ./.github/workflows/release-homebrew-tap.yml
needs:
- sign-and-notarize
with:
ref: ${{ github.event.release.tag_name && format('refs/tags/{0}', github.event.release.tag_name) || inputs.version && format('refs/tags/{0}', inputs.version) || github.ref }}
version: ${{ github.event.release.tag_name || inputs.version || github.ref_name }}
dry-run: false
secrets: inherit