Skip to content

Commit 4ca1b2a

Browse files
committed
Add prepare-release workflow that leverages existing buildkit.yml
Instead of reimplementing release logic, this approach: 1. Uses prepare-patched-release.yml to cherry-pick patches 2. Creates the tag locally but doesn't push 3. Provides manual commands to push the tag 4. Leverages existing buildkit.yml for actual release Benefits: - No PAT needed for patches without workflow changes - Uses upstream's proven build/release process - Manual review step before release - Simpler and more maintainable
1 parent 43061c8 commit 4ca1b2a

File tree

2 files changed

+263
-28
lines changed

2 files changed

+263
-28
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
name: Prepare Patched Release
2+
3+
# This workflow prepares a patched release but DOES NOT push it
4+
# After review, you manually push the tag which triggers buildkit.yml
5+
6+
on:
7+
workflow_dispatch:
8+
inputs:
9+
upstream_version:
10+
description: 'Upstream version to patch (e.g., v0.17.0)'
11+
required: true
12+
type: string
13+
release_suffix:
14+
description: 'Suffix for release (default: blacksmith)'
15+
required: false
16+
type: string
17+
default: 'blacksmith'
18+
19+
permissions:
20+
contents: write
21+
22+
jobs:
23+
prepare-release:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
with:
29+
fetch-depth: 0
30+
31+
- name: Setup git
32+
run: |
33+
git config user.name "GitHub Actions"
34+
git config user.email "actions@github.com"
35+
36+
- name: Add and fetch upstream
37+
run: |
38+
git remote add upstream https://github.com/moby/buildkit.git || true
39+
git fetch upstream master --tags
40+
git fetch origin master
41+
42+
- name: Prepare patched release
43+
id: prepare
44+
run: |
45+
VERSION="${{ github.event.inputs.upstream_version }}"
46+
SUFFIX="${{ github.event.inputs.release_suffix }}"
47+
RELEASE_TAG="${VERSION}-${SUFFIX}"
48+
RELEASE_BRANCH="${VERSION}-${SUFFIX}"
49+
50+
# Check if already exists
51+
if git rev-parse "refs/tags/$RELEASE_TAG" >/dev/null 2>&1; then
52+
echo "❌ Release $RELEASE_TAG already exists"
53+
echo ""
54+
echo "To recreate it, first delete the existing tag:"
55+
echo " git push origin --delete $RELEASE_TAG"
56+
echo " git push origin --delete $RELEASE_BRANCH"
57+
exit 1
58+
fi
59+
60+
# Verify upstream version exists
61+
if ! git rev-parse "refs/tags/$VERSION" >/dev/null 2>&1; then
62+
echo "❌ Upstream version $VERSION not found"
63+
echo ""
64+
echo "Available recent versions:"
65+
git tag -l 'v*.*.*' | grep -v '\-' | sort -rV | head -20
66+
exit 1
67+
fi
68+
69+
# Checkout upstream version
70+
echo "Creating release branch from $VERSION..."
71+
git checkout -b "$RELEASE_BRANCH" "$VERSION"
72+
73+
# Find all commits that are in origin/master but not in upstream/master
74+
echo ""
75+
echo "Finding patches to apply..."
76+
PATCHES=$(git rev-list upstream/master..origin/master --reverse --no-merges)
77+
78+
if [ -z "$PATCHES" ]; then
79+
echo "⚠️ No patches found. Your master branch has no commits ahead of upstream."
80+
exit 1
81+
fi
82+
83+
# Count patches
84+
PATCH_COUNT=$(echo "$PATCHES" | wc -l | tr -d ' ')
85+
echo "Found $PATCH_COUNT patches to apply"
86+
echo ""
87+
88+
# Apply patches and collect results
89+
APPLIED_PATCHES=""
90+
FAILED_PATCHES=""
91+
SUCCESS_COUNT=0
92+
HAS_WORKFLOW_CHANGES=false
93+
94+
for COMMIT in $PATCHES; do
95+
COMMIT_MSG=$(git log -1 --pretty=format:"%h: %s" "$COMMIT")
96+
FULL_MSG=$(git log -1 --pretty=format:"%s" "$COMMIT")
97+
98+
# Check if commit modifies workflow files
99+
WORKFLOW_CHANGES=$(git diff-tree --no-commit-id --name-only -r "$COMMIT" | grep "^.github/workflows/" || true)
100+
if [ -n "$WORKFLOW_CHANGES" ]; then
101+
HAS_WORKFLOW_CHANGES=true
102+
echo "⚠️ Commit $COMMIT_MSG modifies workflow files:"
103+
echo "$WORKFLOW_CHANGES" | sed 's/^/ /'
104+
fi
105+
106+
echo "Applying $COMMIT_MSG..."
107+
if git cherry-pick "$COMMIT" >/dev/null 2>&1; then
108+
echo " ✅ Success"
109+
if [ -n "$APPLIED_PATCHES" ]; then
110+
APPLIED_PATCHES=$(printf "%s\n- %s" "$APPLIED_PATCHES" "$FULL_MSG")
111+
else
112+
APPLIED_PATCHES="- $FULL_MSG"
113+
fi
114+
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
115+
else
116+
echo " ❌ Failed (conflicts with this version)"
117+
if [ -n "$FAILED_PATCHES" ]; then
118+
FAILED_PATCHES=$(printf "%s\n- %s" "$FAILED_PATCHES" "$FULL_MSG")
119+
else
120+
FAILED_PATCHES="- $FULL_MSG"
121+
fi
122+
git cherry-pick --abort || true
123+
fi
124+
done
125+
126+
echo ""
127+
echo "========================================="
128+
echo "Applied $SUCCESS_COUNT out of $PATCH_COUNT patches"
129+
130+
if [ -n "$APPLIED_PATCHES" ]; then
131+
echo ""
132+
echo "✅ Successfully applied:"
133+
echo "$APPLIED_PATCHES"
134+
fi
135+
136+
if [ -n "$FAILED_PATCHES" ]; then
137+
echo ""
138+
echo "⚠️ Failed to apply (incompatible with $VERSION):"
139+
echo "$FAILED_PATCHES"
140+
fi
141+
142+
if [ "$SUCCESS_COUNT" -eq 0 ]; then
143+
echo ""
144+
echo "❌ No patches could be applied to $VERSION"
145+
exit 1
146+
fi
147+
148+
# Create annotated tag locally
149+
TAG_MSG=$(printf "Release %s with %s patches\n\nPatches applied:\n%s" "$VERSION" "$SUCCESS_COUNT" "$APPLIED_PATCHES")
150+
git tag -a "$RELEASE_TAG" -m "$TAG_MSG"
151+
152+
echo ""
153+
echo "========================================="
154+
echo "📦 RELEASE PREPARED SUCCESSFULLY"
155+
echo "========================================="
156+
echo ""
157+
echo "Branch created: $RELEASE_BRANCH"
158+
echo "Tag created: $RELEASE_TAG"
159+
echo ""
160+
161+
if [ "$HAS_WORKFLOW_CHANGES" = true ]; then
162+
echo "⚠️ WARNING: This release contains workflow file changes!"
163+
echo "You'll need a Personal Access Token with 'workflow' scope to push."
164+
echo ""
165+
fi
166+
167+
echo "To complete the release, run these commands locally:"
168+
echo ""
169+
echo " # Clone and setup"
170+
echo " git clone https://github.com/${{ github.repository }}.git"
171+
echo " cd buildkit"
172+
echo " git remote add upstream https://github.com/moby/buildkit.git"
173+
echo " git fetch --all --tags"
174+
echo ""
175+
echo " # Push the release (this will trigger buildkit.yml)"
176+
if [ "$HAS_WORKFLOW_CHANGES" = true ]; then
177+
echo " # Note: Use a PAT with 'workflow' scope for this push"
178+
echo " git push https://<YOUR_PAT>@github.com/${{ github.repository }}.git $RELEASE_TAG"
179+
else
180+
echo " git push origin $RELEASE_TAG"
181+
fi
182+
echo ""
183+
echo " # Optionally push the branch too"
184+
echo " git push origin $RELEASE_BRANCH"
185+
echo ""
186+
echo "Once pushed, the tag will trigger the buildkit.yml workflow"
187+
echo "which will build and release the binaries automatically."
188+
echo ""
189+
190+
# Save info for artifact
191+
cat > release-info.txt << EOF
192+
RELEASE_TAG=$RELEASE_TAG
193+
RELEASE_BRANCH=$RELEASE_BRANCH
194+
VERSION=$VERSION
195+
SUCCESS_COUNT=$SUCCESS_COUNT
196+
HAS_WORKFLOW_CHANGES=$HAS_WORKFLOW_CHANGES
197+
198+
Commands to complete release:
199+
git clone https://github.com/${{ github.repository }}.git
200+
cd buildkit
201+
git remote add upstream https://github.com/moby/buildkit.git
202+
git fetch --all --tags
203+
git push origin $RELEASE_TAG
204+
git push origin $RELEASE_BRANCH
205+
EOF
206+
207+
- name: Create patch summary
208+
if: always()
209+
run: |
210+
if [ -f release-info.txt ]; then
211+
echo "## Release Information"
212+
cat release-info.txt
213+
fi
214+
215+
- name: Upload release info
216+
if: always()
217+
uses: actions/upload-artifact@v4
218+
with:
219+
name: release-info
220+
path: release-info.txt
221+
retention-days: 7

DEPLOYMENT.md

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,56 @@
44

55
This fork maintains patches on top of upstream BuildKit using a rebase workflow. Our `master` branch contains upstream BuildKit plus our custom patches rebased on top.
66

7-
## Setup Requirements
8-
9-
**Required**: You must create a Personal Access Token for the workflows to function properly:
10-
11-
1. Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
12-
2. Click "Generate new token (classic)"
13-
3. Give it a descriptive name (e.g., "BuildKit Fork Workflow")
14-
4. Select these scopes:
15-
- `repo` (all checkboxes under repo)
16-
- `workflow` (update GitHub Action workflows)
17-
5. Generate the token and copy it
18-
6. Go to your fork's Settings > Secrets and variables > Actions
19-
7. Click "New repository secret"
20-
8. Name: `WORKFLOW_TOKEN`
21-
9. Value: Paste your Personal Access Token
22-
23-
This token is necessary because:
24-
- The default `GITHUB_TOKEN` cannot push changes to workflow files
25-
- Some patches may include modifications to `.github/workflows/*.yml` files
7+
## Release Strategy
8+
9+
We use BuildKit's existing `buildkit.yml` workflow to build and release our patched versions. This ensures consistency with upstream's build process.
10+
11+
### Process:
12+
1. **Prepare**: Use `prepare-patched-release.yml` to cherry-pick patches onto an upstream tag
13+
2. **Review**: Check which patches were applied successfully
14+
3. **Push**: Manually push the tag to trigger BuildKit's release workflow
15+
4. **Release**: The existing `buildkit.yml` automatically builds and publishes binaries
2616

2717
## Creating a Patched Release
2818

29-
To deploy a patched version of BuildKit:
19+
### Step 1: Prepare the Release
20+
21+
```bash
22+
# Run the prepare workflow to cherry-pick patches
23+
gh workflow run prepare-patched-release.yml -f upstream_version=v0.17.0
24+
```
25+
26+
This workflow will:
27+
1. Cherry-pick all patches from master onto v0.17.0
28+
2. Create a local tag `v0.17.0-blacksmith`
29+
3. Show you which patches succeeded/failed
30+
4. Give you the exact commands to complete the release
31+
32+
### Step 2: Review and Push
33+
34+
Check the workflow output, then run locally:
3035

3136
```bash
32-
# Create release for v0.17.0 with all our patches
33-
gh workflow run release-patched-version.yml -f upstream_version=v0.17.0
37+
# Clone and setup
38+
git clone https://github.com/useblacksmith/buildkit.git
39+
cd buildkit
40+
git fetch --all --tags
41+
42+
# Push the tag (this triggers buildkit.yml)
43+
git push origin v0.17.0-blacksmith
44+
45+
# The existing buildkit.yml workflow will now:
46+
# - Build multi-platform binaries
47+
# - Create Docker images
48+
# - Publish a GitHub release
3449
```
3550

36-
This workflow:
37-
1. Finds all commits in `origin/master` that aren't in `upstream/master` (our patches)
38-
2. Cherry-picks each patch onto the upstream version tag
39-
3. Builds binaries for Linux and macOS (amd64/arm64)
40-
4. Creates a GitHub release with downloadable artifacts
51+
### Why This Approach?
4152

42-
The release will be tagged as `v0.17.0-blacksmith`.
53+
- **No PAT complexity**: If your patches don't modify workflows, you can use regular git push
54+
- **Uses upstream's build**: The existing `buildkit.yml` handles all the complex build logic
55+
- **Manual control**: You review patches before pushing the release
56+
- **Cleaner**: We don't duplicate BuildKit's release logic
4357

4458
## Keeping Synced with Upstream
4559

0 commit comments

Comments
 (0)