Skip to content

Commit ff7a88f

Browse files
dwoodruff83claude
andauthored
Add release automation + tighten enforce-main-source against forks (#1)
* Add release-on-tag automation workflow When a vX.Y.Z tag is pushed, create a GitHub Release with auto-generated notes. Version 0.x.x tags are marked as pre-releases; 1.x.x+ as full releases. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Tighten enforce-main-source: reject fork PRs Adds a head-repo check so PRs from forks (where the contributor named their branch 'staging') don't pass the source-branch gate. Combined with the collaborator list controlling who can push to this repo's staging, this restricts main merges to repo-write-access only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent cabd031 commit ff7a88f

2 files changed

Lines changed: 57 additions & 2 deletions

File tree

.github/workflows/enforce-main-source.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,18 @@ jobs:
1515
check-source-branch:
1616
runs-on: ubuntu-latest
1717
steps:
18-
- name: Verify source is staging
18+
- name: Verify source is staging from this repo
1919
run: |
20+
# Reject fork PRs. Forks can only PR through staging in their own
21+
# fork, and that source repo isn't this one — block them. Combined
22+
# with the repo's collaborator list controlling who can push to
23+
# this repo's staging, this gates main to repo-write-access only.
24+
if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then
25+
echo "::error::PRs to main must originate from a branch in this repo, not a fork. Source repo: ${{ github.event.pull_request.head.repo.full_name }}"
26+
exit 1
27+
fi
2028
if [ "${{ github.head_ref }}" != "staging" ]; then
2129
echo "::error::PRs to main must come from the 'staging' branch only. Got: '${{ github.head_ref }}'"
2230
exit 1
2331
fi
24-
echo "PR source is 'staging' — OK"
32+
echo "PR source is 'staging' from this repo — OK"

.github/workflows/release.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Create release on tag push
2+
3+
# When a version tag (vX.Y.Z) is pushed, create a corresponding GitHub
4+
# Release. Version 0.x.x tags are marked as pre-releases; 1.x.x+ tags
5+
# are full releases. Release notes auto-generated from commit history
6+
# since the previous tag.
7+
8+
on:
9+
push:
10+
tags:
11+
- 'v*'
12+
13+
permissions:
14+
contents: write
15+
16+
jobs:
17+
release:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
24+
- name: Determine release type
25+
id: type
26+
run: |
27+
TAG="${GITHUB_REF#refs/tags/}"
28+
VERSION="${TAG#v}"
29+
MAJOR="${VERSION%%.*}"
30+
if [ "$MAJOR" = "0" ]; then
31+
echo "prerelease=true" >> "$GITHUB_OUTPUT"
32+
echo "Tag $TAG is 0.x.x — marking as pre-release"
33+
else
34+
echo "prerelease=false" >> "$GITHUB_OUTPUT"
35+
echo "Tag $TAG is $MAJOR.x.x — marking as full release"
36+
fi
37+
38+
- name: Create release
39+
env:
40+
GH_TOKEN: ${{ github.token }}
41+
run: |
42+
TAG="${GITHUB_REF#refs/tags/}"
43+
if [ "${{ steps.type.outputs.prerelease }}" = "true" ]; then
44+
gh release create "$TAG" --generate-notes --prerelease --title "$TAG"
45+
else
46+
gh release create "$TAG" --generate-notes --title "$TAG"
47+
fi

0 commit comments

Comments
 (0)