-
Notifications
You must be signed in to change notification settings - Fork 179
207 lines (177 loc) · 8.99 KB
/
Copy pathnightlydepolyci.yml
File metadata and controls
207 lines (177 loc) · 8.99 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
name: Nightly F-Droid CI
on:
push:
branches:
- main
# The website lives on the deploy branch now, so nothing here needs to be
# excluded to avoid rebuilding the APK for a site-only change.
paths-ignore:
- '.github/workflows/build-nightly.yml'
# A deploy that failed (or was skipped) can be redone by hand — without this
# the only way to re-deploy was an otherwise-pointless commit to main.
workflow_dispatch:
jobs:
build-and-deploy:
name: Build and Deploy Nightly APK to F-Droid
runs-on: ubuntu-latest
steps:
# Step 0: Free up disk space
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: false # Keep Android SDKs for Flutter
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
# Step 1: Checkout the main branch (Shallow clone)
- name: Checkout Main Branch
uses: actions/checkout@v4
with:
fetch-depth: 1
# Step 2: Setup Java
- uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17.x"
# Step 2b: Rust + NDK + cargo-ndk, so the Gradle hook compiles
# libtc_helper.so from rust/ instead of falling back to a prebuilt binary.
- uses: ./.github/actions/setup-rust-android
# Step 3: Setup Flutter
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
# Step 4: Get dependencies
- name: Get dependencies
run: flutter pub get
# Step 5: Decode signing secrets
- name: Decode Signing Secrets
env:
NIGHTLY_KEYSTORE_B64: ${{ secrets.NIGHTLY_KEYSTORE_B64 }}
NIGHTLY_PROPERTIES_B64: ${{ secrets.NIGHTLY_PROPERTIES_B64 }}
run: |
echo "$NIGHTLY_KEYSTORE_B64" | base64 --decode > android/nightly.jks
echo "$NIGHTLY_PROPERTIES_B64" | base64 --decode > android/key_nightly.properties
# Step 6: Build the APK
- name: Build APK
run: flutter build apk --flavor nightly --build-number=${{ github.run_number }} --release
# Step 6b: An APK missing its native library installs fine and then crashes
# at RustLib.init() — fail here rather than deploying it to F-Droid.
- name: Verify native libraries are in the APK
run: ./scripts/verify_apk_native_libs.sh build/app/outputs/flutter-apk/app-nightly-release.apk
# Step 7: Verify the APK is signed
- name: Verify sign
run: keytool -printcert -jarfile build/app/outputs/flutter-apk/app-nightly-release.apk
# Step 7b: Capture which commit is being released.
#
# It has to be captured now: the job switches this work tree to the deploy
# branch further down, and from that point git HEAD is that branch's own
# orphan commit rather than the app commit. The site source lives on the
# deploy branch, so the site itself is built after the switch.
- name: Capture the deployed commit
run: |
echo "DEPLOY_SHA=${{ github.sha }}" >> "$GITHUB_ENV"
echo "DEPLOY_MSG=$(git log -1 --pretty=%s)" >> "$GITHUB_ENV"
# Step 8: Configure git, fetch existing repo, and place new APK
# We fetch the repo so we can see existing APKs to prune them in the next step.
- name: Configure and Prepare Files
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Fetch the target branch to get existing APKs (if branch exists)
git fetch origin fdroid-repo:fdroid-repo || echo "Branch not found, proceeding..."
# stash changes if any
git stash || echo "No changes to stash"
# Switch to that branch or create if it doesn't exist (to setup folder structure)
git checkout fdroid-repo || git checkout --orphan fdroid-repo
# Move the newly built APK into the repo folder
# Ensure repo dir exists
mkdir -p repo
mv build/app/outputs/flutter-apk/app-nightly-release.apk repo/nightly.${{ github.run_number }}.apk
# Step 9: Prune Old APKs, keeping only the 5 most recent
- name: Prune Old APKs
run: |
echo "Checking for old APKs to prune..."
if [ $(ls -1 repo/*.apk 2>/dev/null | wc -l) -gt 5 ]; then
echo "More than 5 APKs found. Deleting all but the 5 most recent..."
ls -1 repo/*.apk | sort -V | head -n -5 | xargs rm -f
else
echo "5 or fewer APKs found. No cleanup needed."
fi
# Step 10: Setup F-Droid and update the repo metadata
- name: Run F-Droid Update
env:
FDROID_CONFIG_YML_B64: ${{ secrets.FDROID_CONFIG_YML }}
FDROID_KEYSTORE_P12_B64: ${{ secrets.FDROID_KEYSTORE_P12 }}
run: |
# Decode the secrets into files
echo $FDROID_CONFIG_YML_B64 | base64 --decode > config.yml
echo $FDROID_KEYSTORE_P12_B64 | base64 --decode > keystore.p12
# Install fdroidserver
sudo apt-get update
sudo apt-get install -y fdroidserver
# Run the update command
fdroid update -c
# Step 10b: Record the deploy and rebuild the site from this branch's own
# source, then place it at the root. Additions only — repo/, metadata/ and
# assets/ are untouched, so F-Droid clients are unaffected.
#
# Guarded: if the deploy branch does not carry the site yet (the website
# PR not merged, or ever rolled back), this step skips with a warning
# instead of failing. It used to die on the missing script, which
# cancelled the push step below — a website problem blocking the APK
# deploy, the one thing this workflow exists to do. When the site source
# IS present, a build failure is still fatal so real breakage stays loud.
- name: Record deploy and rebuild the website
run: |
set -e
if [ ! -f scripts/update_build_log.py ] || [ ! -d website ]; then
echo "::warning::website/ or scripts/update_build_log.py not on the deploy branch — skipping the site rebuild. The F-Droid deploy continues. (Is the website PR merged into fdroid-repo?)"
exit 0
fi
python3 scripts/update_build_log.py success \
"https://github.com/${{ github.repository }}/raw/fdroid-repo/repo/nightly.${{ github.run_number }}.apk" \
"${{ github.run_number }}" "$DEPLOY_SHA" "$DEPLOY_MSG"
# Pinned Hugo rather than a floating action, so a site build cannot
# start failing because an upstream default moved.
HUGO_VERSION=0.164.0
curl -sSL -o /tmp/hugo.tar.gz \
"https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
tar -xzf /tmp/hugo.tar.gz -C /tmp hugo
/tmp/hugo --source website --destination /tmp/site --gc --minify \
--baseURL "https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"
# The generated CNAME is dropped on purpose: no custom domain is
# configured, and committing one would make Pages claim a domain with
# no DNS behind it — taking the site down and breaking the F-Droid repo
# URL that clients already poll.
rm -f /tmp/site/CNAME
cp -R /tmp/site/. .
touch .nojekyll
# Step 11: Push a fresh history with NO bloat
# This creates a temporary orphan branch (no parents) containing ONLY
# the files currently on disk, then force pushes it to replace fdroid-repo.
- name: Push F-Droid updates
run: |
# Create a temporary orphan branch (fresh start, no history)
git checkout --orphan temp_deploy_branch
# Add all files currently on disk (New APK + 4 Old APKs + New Index)
git add .
# Create a new 'Initial Commit'
git commit -m "chore: Update F-Droid repo (Build ${{ github.run_number }})"
# Force push this new state to overwrite fdroid-repo
git push origin temp_deploy_branch:fdroid-repo --force
# Step 12: put the local action definitions back. This job switches the
# work tree to the deploy branch, which does not carry .github/actions/ —
# and post-job steps of composite actions (rust-cache's save) resolve
# their action.yml from the workspace at job END. Without this, every
# run since the branch switch was added has ended "failure" on the post
# step even when the deploy itself fully succeeded — a red X that reads
# as a broken deploy but means nothing. `always()` so it also runs when
# a step after the switch genuinely failed, keeping the real error the
# only one reported.
- name: Restore local action definitions for post-job steps
if: always()
run: git checkout ${{ github.sha }} -- .github/ || true