Skip to content

Commit 83ffc3f

Browse files
committed
refactor: split dev build into separate workflow that only runs on main
Move dev-build job to its own workflow file that only triggers on push to main. This ensures dev builds never run for: - PRs (including release PRs) - Release-please branches - Any branch other than main Benefits: - Clearer separation of concerns - Simpler CI workflow - Impossible for dev builds to run on PRs or release branches
1 parent c79f2e9 commit 83ffc3f

File tree

2 files changed

+164
-168
lines changed

2 files changed

+164
-168
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -109,171 +109,3 @@ jobs:
109109
format: 'table'
110110
exit-code: '1'
111111
severity: 'CRITICAL,HIGH'
112-
113-
check-build-needed:
114-
name: Check if build is needed
115-
runs-on: ubuntu-latest
116-
needs: [test]
117-
outputs:
118-
should-build: ${{ steps.check.outputs.should-build }}
119-
steps:
120-
- name: Checkout code
121-
uses: actions/checkout@v6
122-
with:
123-
fetch-depth: 0
124-
ref: ${{ github.ref }}
125-
sha: ${{ github.sha }}
126-
127-
- name: Check if build should be skipped
128-
id: check
129-
run: |
130-
# Only check for push events (dev-build only runs on push to main)
131-
if [ "${{ github.event_name }}" != "push" ]; then
132-
echo "should-build=false" >> $GITHUB_OUTPUT
133-
exit 0
134-
fi
135-
136-
# Get the current commit SHA
137-
CURRENT_SHA="${{ github.sha }}"
138-
139-
# Get commit message from git log
140-
COMMIT_MSG=$(git log -1 --format="%s" "$CURRENT_SHA" 2>/dev/null || echo "")
141-
142-
echo "Checking commit: $CURRENT_SHA"
143-
echo "Commit message: $COMMIT_MSG"
144-
145-
# Check if it's a release commit (pattern: "chore(main): release" or similar)
146-
# BUT: Always run CI for release-please branches and PRs
147-
if echo "$COMMIT_MSG" | grep -qiE "^(chore|release|version).*(release|version|changelog)"; then
148-
# Check if this is from a release-please branch or PR (should always run CI)
149-
if echo "${{ github.ref }}" | grep -qiE "release-please" || echo "${{ github.head_ref }}" | grep -qiE "release-please"; then
150-
echo "Release commit from release-please branch/PR - running CI"
151-
echo "should-build=true" >> $GITHUB_OUTPUT
152-
exit 0
153-
fi
154-
# Check if commit message explicitly says to skip CI
155-
if echo "$COMMIT_MSG" | grep -qiE "[skip ci]|[ci skip]|skip ci"; then
156-
echo "Skip reason: [skip ci] detected in commit message"
157-
echo "should-build=false" >> $GITHUB_OUTPUT
158-
exit 0
159-
fi
160-
echo "Skip reason: Release commit detected (not from release-please branch)"
161-
echo "should-build=false" >> $GITHUB_OUTPUT
162-
exit 0
163-
fi
164-
165-
# For push events, check changed files against base branch
166-
BASE_SHA="${{ github.event.before }}"
167-
HEAD_SHA="${{ github.event.after }}"
168-
169-
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000" ]; then
170-
# Initial commit or no base, check all files
171-
CHANGED_FILES=$(git ls-tree -r --name-only HEAD)
172-
else
173-
# Get list of changed files
174-
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
175-
fi
176-
177-
if [ -z "$CHANGED_FILES" ]; then
178-
echo "No changed files detected, skipping build"
179-
echo "should-build=false" >> $GITHUB_OUTPUT
180-
exit 0
181-
fi
182-
183-
# Documentation file patterns to ignore
184-
DOC_PATTERNS="^README\.md$|^CHANGELOG\.md$|^docs/|\.md$|^LICENSE"
185-
186-
# Check if all changed files are documentation
187-
NON_DOC_FILES=$(echo "$CHANGED_FILES" | grep -vE "$DOC_PATTERNS" || true)
188-
189-
if [ -z "$NON_DOC_FILES" ]; then
190-
echo "Skip reason: Only documentation files changed"
191-
echo "Changed files:"
192-
echo "$CHANGED_FILES" | sed 's/^/ - /'
193-
echo "should-build=false" >> $GITHUB_OUTPUT
194-
else
195-
echo "Build needed: Non-documentation files changed"
196-
echo "Non-doc files:"
197-
echo "$NON_DOC_FILES" | sed 's/^/ - /'
198-
echo "should-build=true" >> $GITHUB_OUTPUT
199-
fi
200-
201-
dev-build:
202-
name: Development Build
203-
runs-on: ubuntu-latest
204-
needs: [test, check-build-needed]
205-
if: |
206-
github.event_name == 'push' &&
207-
needs.check-build-needed.outputs.should-build == 'true'
208-
permissions:
209-
contents: read
210-
packages: write
211-
212-
steps:
213-
- name: Checkout code
214-
uses: actions/checkout@v6
215-
with:
216-
fetch-depth: 0
217-
ref: ${{ github.ref }}
218-
sha: ${{ github.sha }}
219-
220-
- name: Set up Docker Buildx
221-
uses: docker/setup-buildx-action@v3
222-
223-
- name: Log in to GHCR
224-
uses: docker/login-action@v3
225-
with:
226-
registry: ${{ env.REGISTRY }}
227-
username: ${{ github.actor }}
228-
password: ${{ secrets.GITHUB_TOKEN }}
229-
230-
- name: Generate dev tag
231-
id: meta
232-
run: |
233-
# Create a semver-compatible dev tag with commits since last release and commit SHA
234-
SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)
235-
236-
# Get the last release tag (excluding pre-release tags)
237-
LAST_TAG=$(git describe --tags --abbrev=0 --match="v[0-9]*.[0-9]*.[0-9]*" 2>/dev/null || echo "")
238-
239-
if [ -z "$LAST_TAG" ]; then
240-
# No release tags found, use 0.0.0 and count all commits
241-
VERSION="0.0.0"
242-
COMMIT_COUNT=$(git rev-list --count HEAD)
243-
else
244-
# Extract version from tag (remove 'v' prefix)
245-
VERSION=${LAST_TAG#v}
246-
# Count commits since last release
247-
COMMIT_COUNT=$(git rev-list --count ${LAST_TAG}..HEAD)
248-
fi
249-
250-
DEV_TAG="v${VERSION}-dev.${COMMIT_COUNT}.${SHORT_SHA}"
251-
echo "dev_tag=${DEV_TAG}" >> $GITHUB_OUTPUT
252-
echo "Last release tag: ${LAST_TAG:-'none'}"
253-
echo "Base version: ${VERSION}"
254-
echo "Commits since last release: ${COMMIT_COUNT}"
255-
echo "Generated dev tag: ${DEV_TAG}"
256-
257-
- name: Extract metadata
258-
id: docker_meta
259-
uses: docker/metadata-action@v5
260-
with:
261-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
262-
tags: |
263-
${{ steps.meta.outputs.dev_tag }}
264-
dev
265-
266-
- name: Build and push Docker image
267-
uses: docker/build-push-action@v6
268-
with:
269-
context: .
270-
platforms: linux/amd64,linux/arm64
271-
push: true
272-
tags: ${{ steps.docker_meta.outputs.tags }}
273-
labels: ${{ steps.docker_meta.outputs.labels }}
274-
cache-from: type=gha
275-
cache-to: type=gha,mode=min
276-
build-args: |
277-
VERSION=${{ steps.meta.outputs.dev_tag }}
278-
COMMIT=${{ github.sha }}
279-
BUILD_DATE=${{ github.event.head_commit.timestamp }}

.github/workflows/dev-build.yml

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Dev Build
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths-ignore:
7+
- CHANGELOG.md
8+
- '**.md'
9+
- LICENSE
10+
11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: ${{ github.repository }}
14+
15+
jobs:
16+
check-build-needed:
17+
name: Check if build is needed
18+
runs-on: ubuntu-latest
19+
20+
outputs:
21+
should-build: ${{ steps.check.outputs.should-build }}
22+
steps:
23+
- name: Checkout code
24+
uses: actions/checkout@v6
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Check if build should be skipped
29+
id: check
30+
run: |
31+
# Get the current commit SHA
32+
CURRENT_SHA="${{ github.sha }}"
33+
34+
# Get commit message from git log
35+
COMMIT_MSG=$(git log -1 --format="%s" "$CURRENT_SHA" 2>/dev/null || echo "")
36+
37+
echo "Checking commit: $CURRENT_SHA"
38+
echo "Commit message: $COMMIT_MSG"
39+
40+
# Never build dev images for release commits (they get built by release workflow)
41+
if echo "$COMMIT_MSG" | grep -qiE "^(chore|release|version).*(release|version|changelog)"; then
42+
# Check if commit message explicitly says to skip CI
43+
if echo "$COMMIT_MSG" | grep -qiE "[skip ci]|[ci skip]|skip ci"; then
44+
echo "Skip reason: [skip ci] detected in commit message"
45+
echo "should-build=false" >> $GITHUB_OUTPUT
46+
exit 0
47+
fi
48+
echo "Skip reason: Release commit detected - dev builds only run for non-release commits"
49+
echo "should-build=false" >> $GITHUB_OUTPUT
50+
exit 0
51+
fi
52+
53+
# For push events, check changed files against base branch
54+
BASE_SHA="${{ github.event.before }}"
55+
HEAD_SHA="${{ github.event.after }}"
56+
57+
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000" ]; then
58+
# Initial commit or no base, check all files
59+
CHANGED_FILES=$(git ls-tree -r --name-only HEAD)
60+
else
61+
# Get list of changed files
62+
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
63+
fi
64+
65+
if [ -z "$CHANGED_FILES" ]; then
66+
echo "No changed files detected, skipping build"
67+
echo "should-build=false" >> $GITHUB_OUTPUT
68+
exit 0
69+
fi
70+
71+
# Documentation file patterns to ignore
72+
DOC_PATTERNS="^README\.md$|^CHANGELOG\.md$|^docs/|\.md$|^LICENSE"
73+
74+
# Check if all changed files are documentation
75+
NON_DOC_FILES=$(echo "$CHANGED_FILES" | grep -vE "$DOC_PATTERNS" || true)
76+
77+
if [ -z "$NON_DOC_FILES" ]; then
78+
echo "Skip reason: Only documentation files changed"
79+
echo "Changed files:"
80+
echo "$CHANGED_FILES" | sed 's/^/ - /'
81+
echo "should-build=false" >> $GITHUB_OUTPUT
82+
else
83+
echo "Build needed: Non-documentation files changed"
84+
echo "Non-doc files:"
85+
echo "$NON_DOC_FILES" | sed 's/^/ - /'
86+
echo "should-build=true" >> $GITHUB_OUTPUT
87+
fi
88+
89+
dev-build:
90+
name: Development Build
91+
runs-on: ubuntu-latest
92+
needs: [check-build-needed]
93+
if: needs.check-build-needed.outputs.should-build == 'true'
94+
permissions:
95+
contents: read
96+
packages: write
97+
98+
steps:
99+
- name: Checkout code
100+
uses: actions/checkout@v6
101+
with:
102+
fetch-depth: 0
103+
104+
- name: Set up Docker Buildx
105+
uses: docker/setup-buildx-action@v3
106+
107+
- name: Log in to GHCR
108+
uses: docker/login-action@v3
109+
with:
110+
registry: ${{ env.REGISTRY }}
111+
username: ${{ github.actor }}
112+
password: ${{ secrets.GITHUB_TOKEN }}
113+
114+
- name: Generate dev tag
115+
id: meta
116+
run: |
117+
# Create a semver-compatible dev tag with commits since last release and commit SHA
118+
SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)
119+
120+
# Get the last release tag (excluding pre-release tags)
121+
LAST_TAG=$(git describe --tags --abbrev=0 --match="v[0-9]*.[0-9]*.[0-9]*" 2>/dev/null || echo "")
122+
123+
if [ -z "$LAST_TAG" ]; then
124+
# No release tags found, use 0.0.0 and count all commits
125+
VERSION="0.0.0"
126+
COMMIT_COUNT=$(git rev-list --count HEAD)
127+
else
128+
# Extract version from tag (remove 'v' prefix)
129+
VERSION=${LAST_TAG#v}
130+
# Count commits since last release
131+
COMMIT_COUNT=$(git rev-list --count ${LAST_TAG}..HEAD)
132+
fi
133+
134+
DEV_TAG="v${VERSION}-dev.${COMMIT_COUNT}.${SHORT_SHA}"
135+
echo "dev_tag=${DEV_TAG}" >> $GITHUB_OUTPUT
136+
echo "Last release tag: ${LAST_TAG:-'none'}"
137+
echo "Base version: ${VERSION}"
138+
echo "Commits since last release: ${COMMIT_COUNT}"
139+
echo "Generated dev tag: ${DEV_TAG}"
140+
141+
- name: Extract metadata
142+
id: docker_meta
143+
uses: docker/metadata-action@v5
144+
with:
145+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
146+
tags: |
147+
${{ steps.meta.outputs.dev_tag }}
148+
dev
149+
150+
- name: Build and push Docker image
151+
uses: docker/build-push-action@v6
152+
with:
153+
context: .
154+
platforms: linux/amd64,linux/arm64
155+
push: true
156+
tags: ${{ steps.docker_meta.outputs.tags }}
157+
labels: ${{ steps.docker_meta.outputs.labels }}
158+
cache-from: type=gha
159+
cache-to: type=gha,mode=min
160+
continue-on-error: false
161+
build-args: |
162+
VERSION=${{ steps.meta.outputs.dev_tag }}
163+
COMMIT=${{ github.sha }}
164+
BUILD_DATE=${{ github.event.head_commit.timestamp }}

0 commit comments

Comments
 (0)