Skip to content

Commit 3540fd9

Browse files
committed
release: v1.0.0
0 parents  commit 3540fd9

52 files changed

Lines changed: 11635 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
name: AudioLink CI and Release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
tags:
9+
- "v*"
10+
pull_request:
11+
branches:
12+
- main
13+
- master
14+
workflow_dispatch:
15+
inputs:
16+
tag_name:
17+
description: "Release tag, for example v1.0.0. Leave empty to use Flutter/pubspec.yaml."
18+
required: false
19+
default: ""
20+
type: string
21+
22+
permissions:
23+
contents: read
24+
25+
concurrency:
26+
group: audiolink-${{ github.workflow }}-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
env:
30+
FLUTTER_PROJECT_DIR: Flutter
31+
RUST_PROJECT_DIR: Rust
32+
JAVA_VERSION: "17"
33+
34+
jobs:
35+
verify:
36+
name: Analyze and Test
37+
runs-on: ubuntu-latest
38+
defaults:
39+
run:
40+
working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
41+
42+
steps:
43+
- name: Checkout
44+
uses: actions/checkout@v7
45+
46+
- name: Set up Java
47+
uses: actions/setup-java@v5
48+
with:
49+
distribution: temurin
50+
java-version: ${{ env.JAVA_VERSION }}
51+
cache: gradle
52+
53+
- name: Set up Flutter
54+
uses: subosito/flutter-action@v2
55+
with:
56+
channel: stable
57+
cache: true
58+
59+
- name: Print tool versions
60+
run: |
61+
flutter --version
62+
java -version
63+
64+
- name: Install dependencies
65+
run: flutter pub get
66+
67+
- name: Analyze
68+
run: flutter analyze
69+
70+
- name: Test
71+
run: flutter test
72+
73+
android-release:
74+
name: Build Signed Android Release
75+
runs-on: ubuntu-latest
76+
needs: verify
77+
if: github.event_name != 'pull_request'
78+
permissions:
79+
contents: read
80+
defaults:
81+
run:
82+
working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
83+
84+
steps:
85+
- name: Checkout
86+
uses: actions/checkout@v7
87+
88+
- name: Set up Java
89+
uses: actions/setup-java@v5
90+
with:
91+
distribution: temurin
92+
java-version: ${{ env.JAVA_VERSION }}
93+
cache: gradle
94+
95+
- name: Set up Flutter
96+
uses: subosito/flutter-action@v2
97+
with:
98+
channel: stable
99+
cache: true
100+
101+
- name: Install dependencies
102+
run: flutter pub get
103+
104+
- name: Prepare Android signing
105+
shell: bash
106+
env:
107+
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
108+
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
109+
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
110+
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
111+
run: |
112+
set -euo pipefail
113+
missing=0
114+
for name in ANDROID_KEYSTORE_BASE64 ANDROID_KEY_ALIAS ANDROID_KEY_PASSWORD ANDROID_STORE_PASSWORD; do
115+
if [ -z "${!name:-}" ]; then
116+
echo "::error::Missing repository secret: $name"
117+
missing=1
118+
fi
119+
done
120+
if [ "$missing" -ne 0 ]; then
121+
exit 1
122+
fi
123+
124+
umask 077
125+
printf '%s' "$ANDROID_KEYSTORE_BASE64" | base64 --decode > android/app/release-keystore.jks
126+
{
127+
printf 'storeFile=app/release-keystore.jks\n'
128+
printf 'storePassword=%s\n' "$ANDROID_STORE_PASSWORD"
129+
printf 'keyPassword=%s\n' "$ANDROID_KEY_PASSWORD"
130+
printf 'keyAlias=%s\n' "$ANDROID_KEY_ALIAS"
131+
} > android/key.properties
132+
133+
- name: Resolve release version
134+
id: release_version
135+
shell: bash
136+
run: |
137+
set -euo pipefail
138+
tag_name="${{ inputs.tag_name }}"
139+
if [ -z "$tag_name" ] && [ "${GITHUB_REF_TYPE:-}" = "tag" ]; then
140+
tag_name="$GITHUB_REF_NAME"
141+
fi
142+
143+
version_name="${tag_name#v}"
144+
if [ -z "$tag_name" ]; then
145+
version_name="$(sed -nE 's/^version:[[:space:]]*([^+[:space:]]+).*/\1/p' pubspec.yaml | head -n 1)"
146+
fi
147+
148+
if [ -z "$version_name" ]; then
149+
echo "::error::Unable to resolve Android versionName"
150+
exit 1
151+
fi
152+
153+
echo "tag_name=$tag_name" >> "$GITHUB_OUTPUT"
154+
echo "version_name=$version_name" >> "$GITHUB_OUTPUT"
155+
156+
- name: Build release APK
157+
shell: bash
158+
run: |
159+
set -euo pipefail
160+
flutter build apk --release \
161+
--build-name "${{ steps.release_version.outputs.version_name }}" \
162+
--build-number "$GITHUB_RUN_NUMBER"
163+
164+
- name: Stage release files
165+
shell: bash
166+
run: |
167+
set -euo pipefail
168+
version="${{ steps.release_version.outputs.version_name }}"
169+
release_dir="build/release-assets-${GITHUB_RUN_NUMBER}"
170+
mkdir -p "$release_dir"
171+
172+
cp build/app/outputs/flutter-apk/app-release.apk "$release_dir/AudioLink-Android-${version}.apk"
173+
174+
- name: Upload release artifact
175+
uses: actions/upload-artifact@v7
176+
with:
177+
name: audiolink-android-release-${{ github.run_number }}
178+
path: Flutter/build/release-assets-${{ github.run_number }}/*
179+
if-no-files-found: error
180+
retention-days: 30
181+
182+
rust-windows-release:
183+
name: Build Windows Rust Release
184+
runs-on: windows-latest
185+
needs: verify
186+
if: github.event_name != 'pull_request'
187+
permissions:
188+
contents: read
189+
defaults:
190+
run:
191+
working-directory: ${{ env.RUST_PROJECT_DIR }}
192+
193+
steps:
194+
- name: Checkout
195+
uses: actions/checkout@v7
196+
197+
- name: Set up Rust
198+
shell: pwsh
199+
run: |
200+
rustup default stable
201+
rustc --version
202+
cargo --version
203+
204+
- name: Build release executable
205+
run: cargo build --release --locked
206+
207+
- name: Stage Windows release files
208+
shell: pwsh
209+
run: |
210+
$tagName = "${{ inputs.tag_name }}"
211+
if ([string]::IsNullOrWhiteSpace($tagName) -and $env:GITHUB_REF_TYPE -eq "tag") {
212+
$tagName = $env:GITHUB_REF_NAME
213+
}
214+
215+
$version = $tagName
216+
if ($version.StartsWith("v")) {
217+
$version = $version.Substring(1)
218+
}
219+
if ([string]::IsNullOrWhiteSpace($version)) {
220+
$versionLine = Select-String -Path "..\Flutter\pubspec.yaml" -Pattern '^version:\s*([^+\s]+)' | Select-Object -First 1
221+
if ($versionLine.Line -match '^version:\s*([^+\s]+)') {
222+
$version = $Matches[1]
223+
}
224+
}
225+
if ([string]::IsNullOrWhiteSpace($version)) {
226+
$versionLine = Select-String -Path Cargo.toml -Pattern '^version\s*=\s*"([^"]+)"' | Select-Object -First 1
227+
if ($versionLine.Line -match '^version\s*=\s*"([^"]+)"') {
228+
$version = $Matches[1]
229+
}
230+
}
231+
if ([string]::IsNullOrWhiteSpace($version)) {
232+
Write-Error "Unable to resolve Windows release version"
233+
exit 1
234+
}
235+
236+
$releaseDir = "target\release-package-$env:GITHUB_RUN_NUMBER"
237+
New-Item -ItemType Directory -Force -Path $releaseDir | Out-Null
238+
239+
$exeName = "AudioLink-Windows-$version.exe"
240+
$exePath = "$releaseDir\$exeName"
241+
Copy-Item -LiteralPath "target\release\AudioLink.exe" -Destination $exePath
242+
243+
- name: Upload Windows release artifact
244+
uses: actions/upload-artifact@v7
245+
with:
246+
name: audiolink-windows-release-${{ github.run_number }}
247+
path: Rust/target/release-package-${{ github.run_number }}/*
248+
if-no-files-found: error
249+
retention-days: 30
250+
251+
publish-github-release:
252+
name: Publish GitHub Release
253+
runs-on: ubuntu-latest
254+
needs:
255+
- android-release
256+
- rust-windows-release
257+
if: github.event_name != 'pull_request'
258+
permissions:
259+
contents: write
260+
261+
steps:
262+
- name: Checkout release metadata
263+
uses: actions/checkout@v7
264+
265+
- name: Download release artifacts
266+
uses: actions/download-artifact@v8
267+
with:
268+
path: dist
269+
pattern: audiolink-*-release-${{ github.run_number }}
270+
merge-multiple: true
271+
272+
- name: Create or update GitHub Release
273+
shell: bash
274+
env:
275+
GH_TOKEN: ${{ github.token }}
276+
GH_REPO: ${{ github.repository }}
277+
run: |
278+
set -euo pipefail
279+
tag_name="${{ inputs.tag_name }}"
280+
if [ -z "$tag_name" ] && [ "${GITHUB_REF_TYPE:-}" = "tag" ]; then
281+
tag_name="$GITHUB_REF_NAME"
282+
fi
283+
if [ -z "$tag_name" ]; then
284+
version_name="$(sed -nE 's/^version:[[:space:]]*([^+[:space:]]+).*/\1/p' Flutter/pubspec.yaml | head -n 1)"
285+
if [ -n "$version_name" ]; then
286+
tag_name="v$version_name"
287+
fi
288+
fi
289+
if [ -z "$tag_name" ]; then
290+
echo "::error::Unable to resolve GitHub Release tag"
291+
exit 1
292+
fi
293+
294+
{
295+
printf 'Audio Link %s\n\n' "$tag_name"
296+
printf '%s\n' '- Android APK:用于安装 Android 客户端。'
297+
printf '%s\n' '- Windows EXE:Rust 桌面端程序。'
298+
} > RELEASE_NOTES.md
299+
300+
mapfile -t assets < <(find dist -type f | sort)
301+
if [ "${#assets[@]}" -eq 0 ]; then
302+
echo "::error::No release assets found"
303+
exit 1
304+
fi
305+
306+
if gh release view "$tag_name" >/dev/null 2>&1; then
307+
mapfile -t stale_assets < <(
308+
gh release view "$tag_name" --json assets \
309+
--jq '.assets[].name | select((startswith("AudioLink-Android-") and (endswith(".apk") or endswith(".aab"))) or (startswith("AudioLink-Windows-") and (endswith(".exe") or endswith(".zip"))) or startswith("SHA256SUMS-"))'
310+
)
311+
for stale_asset in "${stale_assets[@]}"; do
312+
gh release delete-asset "$tag_name" "$stale_asset" --yes
313+
done
314+
gh release upload "$tag_name" "${assets[@]}" --clobber
315+
else
316+
gh release create "$tag_name" "${assets[@]}" \
317+
--target "$GITHUB_SHA" \
318+
--title "Audio Link $tag_name" \
319+
--notes-file RELEASE_NOTES.md
320+
fi

Flutter/.gitignore

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.build/
9+
.buildlog/
10+
.history
11+
.svn/
12+
.swiftpm/
13+
migrate_working_dir/
14+
15+
# IntelliJ related
16+
*.iml
17+
*.ipr
18+
*.iws
19+
.idea/
20+
21+
# The .vscode folder contains launch configuration and tasks you configure in
22+
# VS Code which you may wish to be included in version control, so this line
23+
# is commented out by default.
24+
#.vscode/
25+
26+
# Flutter/Dart/Pub related
27+
**/doc/api/
28+
**/ios/Flutter/.last_build_id
29+
.dart_tool/
30+
.flutter-plugins-dependencies
31+
.pub-cache/
32+
.pub/
33+
/build/
34+
/coverage/
35+
36+
# Symbolication related
37+
app.*.symbols
38+
39+
# Obfuscation related
40+
app.*.map.json
41+
42+
# Android Studio will place build artifacts here
43+
/android/app/debug
44+
/android/app/profile
45+
/android/app/release

Flutter/.metadata

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "924134a44c189315be2148659913dda1671cbe99"
8+
channel: "stable"
9+
10+
project_type: app
11+
12+
# Tracks metadata for the flutter migrate command
13+
migration:
14+
platforms:
15+
- platform: root
16+
create_revision: 924134a44c189315be2148659913dda1671cbe99
17+
base_revision: 924134a44c189315be2148659913dda1671cbe99
18+
- platform: android
19+
create_revision: 924134a44c189315be2148659913dda1671cbe99
20+
base_revision: 924134a44c189315be2148659913dda1671cbe99
21+
22+
# User provided section
23+
24+
# List of Local paths (relative to this file) that should be
25+
# ignored by the migrate tool.
26+
#
27+
# Files that are not part of the templates will be ignored by default.
28+
unmanaged_files:
29+
- 'lib/main.dart'
30+
- 'ios/Runner.xcodeproj/project.pbxproj'

0 commit comments

Comments
 (0)