Skip to content

Commit d3c422a

Browse files
arbrandesclaude
andcommitted
build: publish PR packages as pre-releases when labeled
When a PR has the "package" label, CI will run `npm pack` and upload the tarball as a GitHub pre-release. A separate cleanup workflow deletes the pre-release when the PR is closed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bc18e45 commit d3c422a

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,14 @@ jobs:
4343
with:
4444
token: ${{ secrets.CODECOV_TOKEN }}
4545
fail_ci_if_error: true
46+
47+
- name: Pack
48+
if: contains(github.event.pull_request.labels.*.name, 'package')
49+
run: npm pack
50+
51+
- name: Upload package artifact
52+
if: contains(github.event.pull_request.labels.*.name, 'package')
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: npm-package
56+
path: '*.tgz'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Cleanup PR Package
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
jobs:
8+
cleanup:
9+
if: contains(github.event.pull_request.labels.*.name, 'package')
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Delete PR release
14+
env:
15+
GH_TOKEN: ${{ github.token }}
16+
run: |
17+
TAG="pr-${{ github.event.pull_request.number }}"
18+
gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag || true

.github/workflows/pr-package.yml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: Package PR
2+
3+
on:
4+
workflow_run:
5+
workflows: ["node_CI"]
6+
types: [completed]
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
actions: read
12+
13+
jobs:
14+
package:
15+
if: github.event.workflow_run.conclusion == 'success'
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Get PR number
20+
id: pr
21+
env:
22+
GH_TOKEN: ${{ github.token }}
23+
run: |
24+
PR_NUMBER=$(gh api \
25+
"repos/${{ github.repository }}/commits/${{ github.event.workflow_run.head_sha }}/pulls" \
26+
--jq '.[0].number // empty')
27+
if [ -z "$PR_NUMBER" ]; then
28+
echo "Not a PR, skipping"
29+
fi
30+
echo "number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
31+
32+
- name: Check for package label
33+
id: label
34+
if: steps.pr.outputs.number
35+
env:
36+
GH_TOKEN: ${{ github.token }}
37+
run: |
38+
HAS_LABEL=$(gh api \
39+
"repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}" \
40+
--jq '[.labels[].name] | any(. == "package")')
41+
echo "has_label=${HAS_LABEL}" >> "$GITHUB_OUTPUT"
42+
43+
- name: Download artifact
44+
if: steps.label.outputs.has_label == 'true'
45+
uses: actions/download-artifact@v4
46+
with:
47+
name: npm-package
48+
run-id: ${{ github.event.workflow_run.id }}
49+
github-token: ${{ github.token }}
50+
51+
- name: Upload package to a temporary release
52+
if: steps.label.outputs.has_label == 'true'
53+
env:
54+
GH_TOKEN: ${{ github.token }}
55+
run: |
56+
TAG="pr-${{ steps.pr.outputs.number }}"
57+
gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag || true
58+
gh release create "$TAG" *.tgz \
59+
--repo "${{ github.repository }}" \
60+
--target "${{ github.event.workflow_run.head_sha }}" \
61+
--prerelease \
62+
--title "PR #${{ steps.pr.outputs.number }}" \
63+
--notes "Test package for PR #${{ steps.pr.outputs.number }}"
64+
65+
- name: Update PR description with package link
66+
if: steps.label.outputs.has_label == 'true'
67+
env:
68+
GH_TOKEN: ${{ github.token }}
69+
run: |
70+
TAG="pr-${{ steps.pr.outputs.number }}"
71+
ASSET_URL=$(gh release view "$TAG" --repo "${{ github.repository }}" --json assets --jq '.assets[0].url')
72+
73+
gh pr view "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" --json body --jq '.body' > /tmp/pr_body.txt
74+
75+
MARKER_START="<!-- package-link-start -->"
76+
MARKER_END="<!-- package-link-end -->"
77+
78+
if grep -q "$MARKER_START" /tmp/pr_body.txt; then
79+
sed -i "/$MARKER_START/,/$MARKER_END/c\\$MARKER_START\n### Latest PR package\n\n$ASSET_URL\n$MARKER_END" /tmp/pr_body.txt
80+
else
81+
printf '\n%s\n%s\n\n%s\n%s\n' "$MARKER_START" "### Latest PR package" "$ASSET_URL" "$MARKER_END" >> /tmp/pr_body.txt
82+
fi
83+
84+
gh pr edit "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" --body-file /tmp/pr_body.txt

0 commit comments

Comments
 (0)