@@ -3,55 +3,204 @@ name: Release
33on :
44 push :
55 tags :
6- - " v*"
6+ - " v*.*.*"
7+ workflow_dispatch :
8+ inputs :
9+ tag :
10+ description : " Vorhandenen Tag bauen, z. B. v0.2.1"
11+ required : true
12+ type : string
13+
14+ concurrency :
15+ group : release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
16+ cancel-in-progress : false
717
818permissions :
919 contents : write
1020
21+ env :
22+ NODE_VERSION : " 24"
23+ PNPM_VERSION : " 10.33.0"
24+ RELEASE_TAG : ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
25+
1126jobs :
12- publish-tauri :
13- name : release (${{ matrix.platform }})
27+ validate :
28+ name : Release prüfen
29+ runs-on : ubuntu-22.04
30+
31+ steps :
32+ - name : Repository und Release-Tag auschecken
33+ uses : actions/checkout@v7
34+ with :
35+ ref : ${{ env.RELEASE_TAG }}
36+ fetch-depth : 0
37+ persist-credentials : false
38+
39+ - name : Node.js 24 einrichten
40+ uses : actions/setup-node@v6
41+ with :
42+ node-version : ${{ env.NODE_VERSION }}
43+ package-manager-cache : false
44+
45+ - name : Tag und App-Versionen prüfen
46+ shell : bash
47+ run : |
48+ node <<'NODE'
49+ const fs = require('node:fs');
50+
51+ const tag = process.env.RELEASE_TAG;
52+ const match = /^v(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/.exec(tag);
53+ if (!match) {
54+ throw new Error(`Ungültiger Release-Tag: ${tag}. Erwartet wird z. B. v0.2.1.`);
55+ }
56+
57+ const expected = match[1];
58+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
59+ const tauriConfig = JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json', 'utf8'));
60+ const cargoToml = fs.readFileSync('src-tauri/Cargo.toml', 'utf8');
61+ const cargoVersion = /^version\s*=\s*"([^"]+)"/m.exec(cargoToml)?.[1];
62+
63+ const versions = {
64+ 'package.json': packageJson.version,
65+ 'tauri.conf.json': tauriConfig.version,
66+ 'Cargo.toml': cargoVersion,
67+ };
68+
69+ const mismatches = Object.entries(versions)
70+ .filter(([, version]) => version !== expected)
71+ .map(([file, version]) => `${file}: ${version ?? 'fehlt'}`);
72+
73+ if (mismatches.length > 0) {
74+ throw new Error(
75+ `Der Tag ${tag} erwartet Version ${expected}, aber folgende Dateien weichen ab:\n` +
76+ mismatches.join('\n')
77+ );
78+ }
79+
80+ console.log(`Release ${tag} ist konsistent.`);
81+ NODE
82+
83+ prepare-release :
84+ name : Release-Entwurf vorbereiten
85+ needs : validate
86+ runs-on : ubuntu-22.04
87+ outputs :
88+ release_id : ${{ steps.release.outputs.release_id }}
89+ release_url : ${{ steps.release.outputs.release_url }}
90+
91+ steps :
92+ - name : Repository und Release-Tag auschecken
93+ uses : actions/checkout@v7
94+ with :
95+ ref : ${{ env.RELEASE_TAG }}
96+ fetch-depth : 0
97+ persist-credentials : false
98+
99+ - name : GitHub-Release-Entwurf erstellen oder wiederverwenden
100+ id : release
101+ shell : bash
102+ env :
103+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
104+ run : |
105+ cat > release-intro.md <<EOF
106+ ## Code Deck ${RELEASE_TAG}
107+
108+ Lokales Desktop-Dashboard zum Organisieren, Öffnen und Starten von Entwicklungsprojekten.
109+
110+ ### Download
111+ - **Windows:** `.msi` oder `-setup.exe`
112+ - **macOS:** `.dmg` (Universal-Build für Intel und Apple Silicon)
113+ - **Linux:** `.AppImage` oder `.deb`
114+
115+ > Hinweis: Die Builds sind derzeit nicht mit einem kostenpflichtigen Plattform-Zertifikat signiert. Windows SmartScreen oder macOS Gatekeeper können deshalb beim ersten Start nachfragen.
116+ EOF
117+
118+ if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
119+ draft=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}" --jq '.draft')
120+ if [[ "$draft" != "true" ]]; then
121+ echo "::error::Für ${RELEASE_TAG} existiert bereits ein veröffentlichter Release. Bitte verwende einen neuen Tag."
122+ exit 1
123+ fi
124+ echo "Vorhandener Release-Entwurf wird wiederverwendet."
125+ else
126+ prerelease_args=()
127+ if [[ "$RELEASE_TAG" == *-* ]]; then
128+ prerelease_args+=(--prerelease)
129+ fi
130+
131+ gh release create "$RELEASE_TAG" \
132+ --draft \
133+ --verify-tag \
134+ --title "Code Deck ${RELEASE_TAG}" \
135+ --generate-notes \
136+ --notes-file release-intro.md \
137+ "${prerelease_args[@]}"
138+ fi
139+
140+ release_id=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}" --jq '.id')
141+ release_url=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}" --jq '.html_url')
142+ echo "release_id=${release_id}" >> "$GITHUB_OUTPUT"
143+ echo "release_url=${release_url}" >> "$GITHUB_OUTPUT"
144+
145+ build :
146+ name : ${{ matrix.name }}
147+ needs : prepare-release
148+ runs-on : ${{ matrix.platform }}
149+
14150 strategy :
15151 fail-fast : false
16152 matrix :
17153 include :
18- - platform : macos-15
19- args : --target universal-apple-darwin
20- - platform : ubuntu-22.04
154+ - name : Windows
155+ platform : windows-latest
21156 args : " "
22- - platform : windows-latest
157+ rust_targets : " "
158+ - name : Linux
159+ platform : ubuntu-22.04
23160 args : " "
161+ rust_targets : " "
162+ - name : macOS Universal
163+ platform : macos-15
164+ args : " --target universal-apple-darwin"
165+ rust_targets : " aarch64-apple-darwin,x86_64-apple-darwin"
24166
25- runs-on : ${{ matrix.platform }}
26167
27168 steps :
28- - name : Checkout repository
169+ - name : Repository und Release-Tag auschecken
29170 uses : actions/checkout@v7
171+ with :
172+ ref : ${{ env.RELEASE_TAG }}
173+ fetch-depth : 0
174+ persist-credentials : false
30175
31- - name : Set up pnpm
176+ - name : pnpm einrichten
32177 uses : pnpm/action-setup@v6
33178 with :
34- version : 10.33.0
179+ version : ${{ env.PNPM_VERSION }}
180+ run_install : false
35181
36- - name : Set up Node.js
182+ - name : Node.js 24 mit pnpm-Cache einrichten
37183 uses : actions/setup-node@v6
38184 with :
39- node-version : 24
185+ node-version : ${{ env.NODE_VERSION }}
40186 cache : pnpm
41187 cache-dependency-path : pnpm-lock.yaml
188+ package-manager-cache : false
42189
43- - name : Set up Rust
190+ - name : Rust stable einrichten
44191 uses : dtolnay/rust-toolchain@stable
45192 with :
46- targets : ${{ matrix.platform == 'macos-15' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
193+ targets : ${{ matrix.rust_targets }}
47194
48- - name : Cache Rust build artifacts
195+ - name : Rust-Buildcache einrichten
49196 uses : swatinem/rust-cache@v2
50197 with :
51198 workspaces : src-tauri -> target
199+ shared-key : release-${{ matrix.platform }}
52200
53- - name : Install Linux system dependencies
201+ - name : Linux-Systempakete installieren
54202 if : matrix.platform == 'ubuntu-22.04'
203+ shell : bash
55204 run : |
56205 sudo apt-get update
57206 sudo apt-get install -y \
@@ -61,17 +210,41 @@ jobs:
61210 patchelf \
62211 xdg-utils
63212
64- - name : Install frontend dependencies
213+ - name : Frontend-Abhängigkeiten reproduzierbar installieren
65214 run : pnpm install --frozen-lockfile
66215
67- - name : Build and publish Tauri application
216+ - name : Tauri-App bauen und Release-Artefakte hochladen
68217 uses : tauri-apps/tauri-action@v1
69218 env :
70219 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
71220 with :
72- tagName : ${{ github.ref_name }}
73- releaseName : " Code Deck ${{ github.ref_name }}"
74- releaseBody : " See CHANGELOG.md for details."
221+ releaseId : ${{ needs.prepare-release.outputs.release_id }}
222+ tagName : ${{ env.RELEASE_TAG }}
75223 releaseDraft : true
76- prerelease : false
224+ prerelease : ${{ contains(env.RELEASE_TAG, '-') }}
225+ retryAttempts : 2
226+ releaseAssetNamePattern : " Code-Deck_[version]_[platform]_[arch][setup][ext]"
227+ uploadWorkflowArtifacts : true
228+ workflowArtifactNamePattern : " Code-Deck_[version]_[platform]_[arch]_[bundle]"
77229 args : ${{ matrix.args }}
230+
231+ done :
232+ name : Release bereit
233+ needs :
234+ - prepare-release
235+ - build
236+ runs-on : ubuntu-22.04
237+
238+ steps :
239+ - name : Zusammenfassung schreiben
240+ shell : bash
241+ run : |
242+ {
243+ echo "## Code Deck ${RELEASE_TAG} ist gebaut"
244+ echo
245+ echo "Alle Plattform-Artefakte wurden in den Release-Entwurf hochgeladen."
246+ echo
247+ echo "Öffne den Entwurf unter: ${{ needs.prepare-release.outputs.release_url }}"
248+ echo
249+ echo "Prüfe die Dateien und klicke anschließend auf **Publish release**."
250+ } >> "$GITHUB_STEP_SUMMARY"
0 commit comments