-
Notifications
You must be signed in to change notification settings - Fork 0
200 lines (177 loc) · 6.4 KB
/
Copy pathbuild.yml
File metadata and controls
200 lines (177 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
name: Build and Publish Container
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
schedule:
# Run every Monday at 6:00 AM UTC
- cron: '0 6 * * 1'
workflow_dispatch: {}
permissions:
contents: write
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ghcr.io/devrail-dev/dev-toolchain
jobs:
# Auto-version bump for scheduled and manual builds
auto-version:
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
new_tag: ${{ steps.bump.outputs.new_tag }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine next patch version
id: bump
run: |
# Get the latest semver tag
LATEST_TAG=$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n1)
if [ -z "${LATEST_TAG}" ]; then
NEW_TAG="v1.0.0"
echo "No existing tags found, starting at ${NEW_TAG}"
else
# Parse components
MAJOR=$(echo "${LATEST_TAG}" | sed 's/v//' | cut -d. -f1)
MINOR=$(echo "${LATEST_TAG}" | sed 's/v//' | cut -d. -f2)
PATCH=$(echo "${LATEST_TAG}" | sed 's/v//' | cut -d. -f3)
# Increment patch
NEW_TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
echo "Bumping ${LATEST_TAG} -> ${NEW_TAG}"
fi
echo "new_tag=${NEW_TAG}" >> "$GITHUB_OUTPUT"
- name: Create and push new tag
run: |
NEW_TAG="${{ steps.bump.outputs.new_tag }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "${NEW_TAG}"
git push origin "${NEW_TAG}"
# Build and push the container image
build-and-push:
needs: [auto-version]
if: always() && (needs.auto-version.result == 'success' || needs.auto-version.result == 'skipped')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine tag for build
id: tag
run: |
if [ "${{ github.event_name }}" == "push" ]; then
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
else
echo "tag=${{ needs.auto-version.outputs.new_tag }}" >> "$GITHUB_OUTPUT"
fi
- name: Set up QEMU for multi-arch
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},value=${{ steps.tag.outputs.tag }}
type=semver,pattern=v{{major}},value=${{ steps.tag.outputs.tag }}
labels: |
org.opencontainers.image.source=https://github.com/devrail-dev/dev-toolchain
org.opencontainers.image.description=DevRail developer toolchain container
org.opencontainers.image.licenses=MIT
- name: Build and push multi-arch image
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Generate and attach tool version manifest to GitHub release
version-manifest:
needs: [build-and-push]
if: always() && needs.build-and-push.result == 'success' && startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write
packages: read
steps:
- name: Determine version
id: version
run: |
# Strip v prefix: v1.4.2 → 1.4.2 (metadata-action tags images without v)
TAG="${GITHUB_REF_NAME}"
VERSION="${TAG#v}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull published image
run: docker pull ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
- name: Generate tool version manifest
run: |
docker run --rm \
${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} \
bash /opt/devrail/scripts/report-tool-versions.sh \
> tool-versions.json
- name: Upload manifest to GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
run: |
TAG="${{ steps.version.outputs.tag }}"
for attempt in 1 2 3 4 5; do
if gh release upload "${TAG}" tool-versions.json --clobber; then
echo "Uploaded tool-versions.json to release ${TAG}"
exit 0
fi
echo "Attempt ${attempt}/5 failed — retrying in 10s"
sleep 10
done
echo "Failed to upload after 5 attempts"
exit 1
# Notify on failure
notify-failure:
needs: [build-and-push, version-manifest]
if: failure()
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Create issue on build failure
uses: actions/github-script@v7
with:
script: |
const title = `Build failed: ${new Date().toISOString().split('T')[0]}`;
const body = [
'The container build failed.',
'',
`**Trigger:** ${context.eventName}`,
`**Workflow run:** ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
'',
'Please investigate and fix the build.',
].join('\n');
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['build-failure', 'automated']
});