Skip to content

Commit 7607bc7

Browse files
ci: add pre-release workflow for per-PR dev builds
Add a GitHub Actions workflow that builds and publishes pre-release packages to Cloudsmith for manual testing on a per-PR basis. Trigger by either: - Adding the 'pre-release' label to a PR - Commenting '/pre-release' on a PR (collaborators only) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c7eabc7 commit 7607bc7

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed

.github/workflows/pre-release.yml

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Pre-release workflow: Build and publish dev packages to Cloudsmith for manual testing.
2+
#
3+
# Trigger by either:
4+
# 1. Adding the 'pre-release' label to a PR
5+
# 2. Commenting '/pre-release' on a PR (must be repo collaborator)
6+
#
7+
# The pre-release version is {base}.dev{pr_number}{epoch} (e.g. 1.13.0.dev421741712838).
8+
# Each re-trigger produces a unique version so previous pre-releases are preserved.
9+
10+
name: Pre-release
11+
12+
on:
13+
pull_request:
14+
types: [labeled]
15+
issue_comment:
16+
types: [created]
17+
18+
concurrency:
19+
group: pre-release-${{ github.event.pull_request.number || github.event.issue.number }}
20+
cancel-in-progress: true
21+
22+
jobs:
23+
pre-release:
24+
name: Build and publish pre-release
25+
# Trigger on 'pre-release' label OR '/pre-release' comment from a collaborator
26+
if: >-
27+
(github.event_name == 'pull_request' &&
28+
github.event.label.name == 'pre-release') ||
29+
(github.event_name == 'issue_comment' &&
30+
github.event.issue.pull_request &&
31+
startsWith(github.event.comment.body, '/pre-release') &&
32+
contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
33+
runs-on: ubuntu-latest
34+
permissions:
35+
id-token: write
36+
contents: read
37+
pull-requests: write
38+
env:
39+
CLOUDSMITH_NAMESPACE: ${{ vars.CLOUDSMITH_NAMESPACE }}
40+
CLOUDSMITH_SVC_SLUG: ${{ vars.CLOUDSMITH_SVC_SLUG }}
41+
steps:
42+
- name: React to slash command
43+
if: github.event_name == 'issue_comment'
44+
env:
45+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
COMMENT_ID: ${{ github.event.comment.id }}
47+
REPO: ${{ github.repository }}
48+
run: |
49+
gh api "repos/${REPO}/issues/comments/${COMMENT_ID}/reactions" \
50+
-f content=eyes --silent
51+
52+
- name: Resolve PR details
53+
id: pr
54+
env:
55+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56+
EVENT_NAME: ${{ github.event_name }}
57+
ISSUE_NUMBER: ${{ github.event.issue.number }}
58+
PR_NUMBER_LABEL: ${{ github.event.pull_request.number }}
59+
REPO: ${{ github.repository }}
60+
run: |
61+
if [ "${EVENT_NAME}" = "issue_comment" ]; then
62+
PR_NUMBER="${ISSUE_NUMBER}"
63+
else
64+
PR_NUMBER="${PR_NUMBER_LABEL}"
65+
fi
66+
echo "number=${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
67+
68+
PR_JSON=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}")
69+
echo "sha=$(echo "${PR_JSON}" | jq -r .head.sha)" >> "${GITHUB_OUTPUT}"
70+
71+
# Block builds from forked PRs (the fork code would run with repo secrets)
72+
IS_FORK=$(echo "${PR_JSON}" | jq -r '.head.repo.fork // false')
73+
if [ "${IS_FORK}" = "true" ]; then
74+
echo "::error::Pre-release builds are not supported for PRs from forks"
75+
exit 1
76+
fi
77+
78+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
79+
with:
80+
ref: ${{ steps.pr.outputs.sha }}
81+
persist-credentials: false
82+
83+
- name: Set up Python 3.10
84+
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 6.1.0
85+
with:
86+
python-version: "3.10"
87+
88+
- name: Set pre-release version
89+
id: version
90+
env:
91+
PR_NUMBER: ${{ steps.pr.outputs.number }}
92+
run: |
93+
BASE_VERSION=$(cat VERSION)
94+
EPOCH=$(date +%s)
95+
PRE_VERSION="${BASE_VERSION}.dev${PR_NUMBER}${EPOCH}"
96+
echo "${PRE_VERSION}" > VERSION
97+
echo "${PRE_VERSION}" > cloudsmith_cli/data/VERSION
98+
echo "version=${PRE_VERSION}" >> "${GITHUB_OUTPUT}"
99+
100+
- name: Install build dependencies
101+
run: |
102+
python -m pip install --upgrade pip
103+
pip install setuptools wheel
104+
105+
- name: Build packages
106+
run: python setup.py sdist bdist_wheel
107+
108+
- name: Install and authenticate Cloudsmith CLI
109+
uses: cloudsmith-io/cloudsmith-cli-action@76c8ff51a34bea1036d9b7708f10a929624a1910 # v2.0.1
110+
with:
111+
oidc-namespace: ${{ vars.CLOUDSMITH_NAMESPACE }}
112+
oidc-service-slug: ${{ vars.CLOUDSMITH_SVC_SLUG }}
113+
114+
- name: Publish to Cloudsmith
115+
env:
116+
PKG_REPO: ${{ vars.CLOUDSMITH_NAMESPACE }}/cli
117+
run: |
118+
cloudsmith push python "${PKG_REPO}" dist/*.tar.gz --republish
119+
cloudsmith push python "${PKG_REPO}" dist/*.whl --republish
120+
121+
- name: Comment on PR with install instructions
122+
env:
123+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
124+
VERSION: ${{ steps.version.outputs.version }}
125+
PR_NUMBER: ${{ steps.pr.outputs.number }}
126+
HEAD_SHA: ${{ steps.pr.outputs.sha }}
127+
REPO: ${{ github.repository }}
128+
CS_NS: ${{ vars.CLOUDSMITH_NAMESPACE }}
129+
run: |
130+
cat > /tmp/comment.md << COMMENT
131+
🚀 **Pre-release \`${VERSION}\` published to Cloudsmith!**
132+
133+
Install with:
134+
\`\`\`
135+
pip install --extra-index-url https://dl.cloudsmith.io/public/${CS_NS}/cli/python/simple/ cloudsmith-cli==${VERSION}
136+
\`\`\`
137+
138+
_Built from ${HEAD_SHA}_
139+
COMMENT
140+
gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body-file /tmp/comment.md
141+
142+
- name: Remove pre-release label
143+
if: github.event_name == 'pull_request'
144+
env:
145+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
146+
PR_NUMBER: ${{ steps.pr.outputs.number }}
147+
REPO: ${{ github.repository }}
148+
run: |
149+
gh pr edit "${PR_NUMBER}" --repo "${REPO}" --remove-label pre-release || true

0 commit comments

Comments
 (0)