Repository navigation
236 lines (215 loc) · 8.84 KB
/
Copy pathrelease.yml
File metadata and controls
236 lines (215 loc) · 8.84 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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
name: Release
# Auto-bump + tag + image Docker + page GitHub Releases.
# L’assistant Windows et le Flatpak Linux sont dans images.yml (déclenché après
# chaque Release réussie, plus un filet quotidien).
# Si la version Cargo.toml est déjà publiée, GitHub incrémente le patch automatiquement.
# Les pushes faits avec GITHUB_TOKEN ne re-déclenchent pas de workflow (pas de boucle).
on:
push:
branches: [main]
tags:
- "v*"
workflow_dispatch:
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write
packages: write
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
should_release: ${{ steps.meta.outputs.should_release }}
version: ${{ steps.meta.outputs.version }}
tag: ${{ steps.meta.outputs.tag }}
sha: ${{ steps.meta.outputs.sha }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- id: meta
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
read_cargo_version() {
awk '/^\[workspace.package\]/{f=1} f && $1=="version"{gsub(/"/,"",$3); print $3; exit}' Cargo.toml
}
bump_patch() {
local v="$1" major minor patch
IFS=. read -r major minor patch <<< "$v"
echo "${major}.${minor}.$((patch + 1))"
}
apply_version() {
local old="$1" new="$2"
sed -i "s/^version = \"${old}\"/version = \"${new}\"/" Cargo.toml
sed -i "0,/\"version\": \"${old}\"/s//\"version\": \"${new}\"/" apps/web/package.json
# Uniquement les crates du workspace. Un `sed` global réécrit aussi
# les dépendances qui ont le même numéro (ex. syn 2.0.119).
awk -v old="$old" -v new="$new" '
/^name = "devforge/ { hit = 1 }
hit && $0 == "version = \"" old "\"" {
sub(old, new)
hit = 0
}
{ print }
' Cargo.lock > Cargo.lock.tmp
mv Cargo.lock.tmp Cargo.lock
}
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
VERSION="${GITHUB_REF_NAME#v}"
else
VERSION=$(read_cargo_version)
if [[ -z "$VERSION" ]]; then
echo "Impossible de lire la version"
exit 1
fi
# GitHub gère les versions : release déjà là, ou tag figé alors que
# HEAD a avancé (job web KO → pas de GitHub Release) → bump patch.
NEED_BUMP=false
if gh release view "v${VERSION}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
NEED_BUMP=true
echo "Release v${VERSION} déjà sur GitHub"
elif git rev-parse "refs/tags/v${VERSION}" >/dev/null 2>&1; then
TAG_SHA="$(git rev-list -n 1 "v${VERSION}")"
HEAD_SHA="$(git rev-parse HEAD)"
if [[ "$TAG_SHA" != "$HEAD_SHA" ]]; then
NEED_BUMP=true
echo "Tag v${VERSION} existe sans release GitHub, HEAD a avancé"
fi
fi
if [[ "$NEED_BUMP" == "true" ]]; then
OLD="$VERSION"
VERSION=$(bump_patch "$OLD")
echo "Auto-bump GitHub: ${OLD} → ${VERSION}"
apply_version "$OLD" "$VERSION"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock apps/web/package.json
git commit -m "chore: bump version ${OLD} → ${VERSION}"
git push origin "HEAD:${GITHUB_REF_NAME}"
else
echo "Version ${VERSION} pas encore publiée — release directe"
fi
fi
TAG="v${VERSION}"
SHOULD=true
if gh release view "${TAG}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
echo "Release ${TAG} déjà publiée — skip"
SHOULD=false
fi
# Le tag git est créé après le push Docker : l’appli le prend pour
# « version disponible » et lancerait un pull trop tôt sinon.
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
echo "should_release=${SHOULD}" >> "$GITHUB_OUTPUT"
docker:
needs: prepare
if: needs.prepare.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.prepare.outputs.sha }}
fetch-depth: 0
fetch-tags: true
- uses: docker/setup-buildx-action@v3
- name: Login GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker tags
run: |
set -euo pipefail
VERSION="${{ needs.prepare.outputs.version }}"
OWNER_LC="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')"
HUB_USER="${{ secrets.DOCKERHUB_USERNAME }}"
TAGS="ghcr.io/${OWNER_LC}/devforge:${VERSION},ghcr.io/${OWNER_LC}/devforge:latest"
TAGS="${TAGS},${HUB_USER}/devforge:${VERSION},${HUB_USER}/devforge:latest"
if [[ "$VERSION" =~ ^([0-9]+\.[0-9]+)\. ]]; then
MINOR="${BASH_REMATCH[1]}"
TAGS="${TAGS},ghcr.io/${OWNER_LC}/devforge:${MINOR},${HUB_USER}/devforge:${MINOR}"
fi
echo "TAGS=${TAGS}" >> "$GITHUB_ENV"
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ env.TAGS }}
- name: Publier le tag puis la page GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="${{ needs.prepare.outputs.tag }}"
if [[ "${GITHUB_REF_TYPE}" != "tag" ]]; then
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if ! git rev-parse "refs/tags/${TAG}" >/dev/null 2>&1; then
git tag -a "${TAG}" -m "DevForge ${TAG}"
git push origin "refs/tags/${TAG}"
fi
fi
gh release create "$TAG" \
--repo "${{ github.repository }}" \
--title "DevForge ${TAG}" \
--generate-notes
# APK Android signé, joint à la page GitHub Release créée par le job docker.
android:
needs: [prepare, docker]
if: needs.prepare.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.prepare.outputs.sha }}
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- uses: gradle/actions/setup-gradle@v4
- name: Clé de signature
env:
KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
set -euo pipefail
if [[ -n "${KEYSTORE_B64}" ]]; then
echo "${KEYSTORE_B64}" | base64 -d > "${RUNNER_TEMP}/release.jks"
echo "DEVFORGE_KEYSTORE_FILE=${RUNNER_TEMP}/release.jks" >> "$GITHUB_ENV"
echo "APK_SUFFIX=" >> "$GITHUB_ENV"
else
echo "::warning::ANDROID_KEYSTORE_BASE64 absent : APK signé avec la clé debug"
echo "APK_SUFFIX=-debug-signed" >> "$GITHUB_ENV"
fi
- name: Build APK release
working-directory: apps/android
env:
DEVFORGE_VERSION: ${{ needs.prepare.outputs.version }}
DEVFORGE_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
DEVFORGE_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
DEVFORGE_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: ./gradlew --no-daemon :app:assembleRelease
- name: Joindre l'APK à la release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
VERSION="${{ needs.prepare.outputs.version }}"
TAG="${{ needs.prepare.outputs.tag }}"
SRC=apps/android/app/build/outputs/apk/release/app-release.apk
cp "$SRC" "DevForge-Android-${VERSION}${APK_SUFFIX}.apk"
# Nom stable : …/releases/latest/download/DevForge-Android.apk
cp "$SRC" "DevForge-Android${APK_SUFFIX}.apk"
gh release upload "$TAG" "DevForge-Android-${VERSION}${APK_SUFFIX}.apk" "DevForge-Android${APK_SUFFIX}.apk" \
--repo "${{ github.repository }}" --clobber
rm -f "${RUNNER_TEMP}/release.jks"