Skip to content

Publish

Publish #107

Workflow file for this run

name: Publish
on:
release:
types: [published]
jobs:
find-artifacts:
name: Find CI artifacts
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
outputs:
ci-run-id: ${{ steps.find.outputs.run-id }}
needs-build: ${{ steps.find.outputs.needs-build }}
steps:
- name: Find successful CI run for release target
id: find
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET: ${{ github.event.release.target_commitish }}
shell: bash
run: |
# Resolve branch name or tag to a commit SHA
SHA=$(gh api "repos/$GITHUB_REPOSITORY/commits/$TARGET" --jq '.sha' 2>/dev/null || echo "$TARGET")
echo "Resolved target '$TARGET' to SHA: $SHA"
# Find the most recent successful CI run for this SHA that has a build artifact
RUN_ID=$(gh api "repos/$GITHUB_REPOSITORY/actions/workflows/ci.yml/runs" \
-F "head_sha=$SHA" \
-F "status=success" \
-F "per_page=10" \
--jq '.workflow_runs[].id') || {
echo "::error::Failed to query CI workflow runs. If ci.yml was renamed, update the reference in the find-artifacts job in publish.yml."
exit 1
}
USABLE_RUN_ID=""
for ID in $RUN_ID; do
HAS_ARTIFACT=$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$ID/artifacts" \
--jq '[.artifacts[] | select(.name == "build" and .expired == false)] | length')
if [ "$HAS_ARTIFACT" -gt 0 ]; then
USABLE_RUN_ID="$ID"
break
fi
done
if [ -z "$USABLE_RUN_ID" ]; then
echo "No successful CI run with a valid build artifact found for SHA $SHA. A fresh build will be triggered."
echo "run-id=" >> "$GITHUB_OUTPUT"
echo "needs-build=true" >> "$GITHUB_OUTPUT"
else
echo "Found suitable CI run: $USABLE_RUN_ID"
echo "run-id=$USABLE_RUN_ID" >> "$GITHUB_OUTPUT"
echo "needs-build=false" >> "$GITHUB_OUTPUT"
fi
build:
name: Build (no prior CI run found)
needs: find-artifacts
if: ${{ needs.find-artifacts.outputs.needs-build == 'true' }}
uses: ./.github/workflows/ci.yml
with:
force-full-build: true
cd:
name: Publish to npm
needs:
- find-artifacts
- build
# Run if find-artifacts succeeded AND (build succeeded OR build was skipped because artifacts already exist)
if: ${{ !cancelled() && needs.find-artifacts.result == 'success' && (needs.build.result == 'success' || needs.build.result == 'skipped') }}
runs-on: ubuntu-latest
permissions:
actions: read # to download artifacts from the CI run
contents: write # to push the version commit and tag
issues: write # to comment on issues when a fix is released
pull-requests: write # to comment on PRs when a fix is released
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- name: Debug info
# https://docs.github.com/en/actions/reference/security/secure-use#use-an-intermediate-environment-variable
env:
# `env:` values are printed to the log even without using them in `run:`
RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
RELEASE_TARGET_COMMITISH: ${{ github.event.release.target_commitish }}
run: |
cat <<EOF
Release tag name: $RELEASE_TAG_NAME
Release target commit-ish: $RELEASE_TARGET_COMMITISH
EOF
- name: Determine NPM tag
shell: bash
env:
TARGET_COMMITISH: ${{ github.event.release.target_commitish }}
IS_PRERELEASE: ${{ github.event.release.prerelease }}
run: |
case "$TARGET_COMMITISH" in
develop | main | master)
if [[ "$IS_PRERELEASE" == true ]]; then
npm_tag=beta
else
npm_tag=latest
fi
;;
*)
# use the branch name as the npm tag
npm_tag="$TARGET_COMMITISH"
;;
esac
echo "Determined NPM tag: [$npm_tag]"
echo "NPM_TAG=${npm_tag}" >> "$GITHUB_ENV"
- name: Check NPM tag
run: |
if [ -z "$NPM_TAG" ]; then
echo "Refusing to publish with empty NPM tag."
exit 1
fi
- name: Config GitHub user
shell: bash
run: |
git config --global user.name 'GitHub Actions'
git config --global user.email 'github-actions@localhost'
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
token: ${{ secrets.PAT_RELEASE_PUSH }} # persists the token for pushing to the repo later
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
cache: 'npm'
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
- uses: ./.github/actions/install-dependencies
- name: Download build artifacts (from previous CI run)
if: ${{ needs.build.result == 'skipped' }}
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: build
path: packages
run-id: ${{ needs.find-artifacts.outputs.ci-run-id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Download build artifacts (from fallback build in this run)
if: ${{ needs.build.result == 'success' }}
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: build
path: packages
- name: Update the version in the package files
shell: bash
env:
GIT_TAG: ${{ github.event.release.tag_name }}
run: |
NEW_VERSION="${GIT_TAG/v/}"
npm version "$NEW_VERSION" --no-git-tag-version
git add package* && git commit -m "chore(release): $NEW_VERSION [skip ci]"
- name: Publish scratch-svg-renderer
run: npm publish --access=public --tag="$NPM_TAG" --ignore-scripts --workspace=@scratch/scratch-svg-renderer
- name: Publish scratch-render
run: npm publish --access=public --tag="$NPM_TAG" --ignore-scripts --workspace=@scratch/scratch-render
- name: Publish scratch-vm
run: npm publish --access=public --tag="$NPM_TAG" --ignore-scripts --workspace=@scratch/scratch-vm
- name: Publish scratch-gui
run: |
cp ./packages/scratch-gui/package.json ./packages/scratch-gui/package-copy.json
jq 'del(.exports["./standalone"])' ./packages/scratch-gui/package.json | npx sponge ./packages/scratch-gui/package.json
npm publish --access=public --tag="$NPM_TAG" --ignore-scripts --workspace=@scratch/scratch-gui
mv ./packages/scratch-gui/package-copy.json ./packages/scratch-gui/package.json
- name: Publish scratch-gui-standalone
run: |
bash ./scripts/prepare-standalone-gui.sh
npm publish --access=public --tag="$NPM_TAG" --ignore-scripts --workspace=@scratch/scratch-gui-standalone
- name: Publish task-herder
run: npm publish --access=public --tag="$NPM_TAG" --ignore-scripts --workspace=@scratch/task-herder
- name: Publish scratch-media-lib-scripts
run: |
npm run build --workspace @scratch/scratch-media-lib-scripts
npm publish --access=public --tag="${{steps.npm_tag.outputs.npm_tag}}" --workspace=@scratch/scratch-media-lib-scripts
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
- name: Push to develop
shell: bash
env:
TAG_NAME: ${{ github.event.release.tag_name }}
run: |
git fetch origin develop
LAST_COMMIT_ID="$(git rev-parse "$TAG_NAME")"
DEVELOP_COMMIT_ID="$(git rev-parse origin/develop)"
if [ "$LAST_COMMIT_ID" = "$DEVELOP_COMMIT_ID" ]; then
git push origin HEAD:develop
else
echo "Not pushing to develop because the tag we're operating on is behind"
fi
- name: Comment on resolved issues and merged PRs
if: ${{ !github.event.release.prerelease }}
uses: apexskier/github-release-commenter@e7813a9625eabd79a875b4bc4046cfcae377ab34 # v1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
comment-template: |
:tada: This is included in release {release_link}.
# See https://stackoverflow.com/a/24849501
- name: Change connected commit on release
shell: bash
env:
TAG_NAME: ${{ github.event.release.tag_name }}
run: |
git tag -f "$TAG_NAME" HEAD
git push -f origin "refs/tags/$TAG_NAME"