Skip to content

Commit 4e37e00

Browse files
committed
chore: add CI to publish Flatpak to Mixxx repo
1 parent ea97894 commit 4e37e00

3 files changed

Lines changed: 187 additions & 6 deletions

File tree

.github/workflows/flatpak.yml

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
name: Flatpak
2+
on:
3+
workflow_call:
4+
inputs:
5+
update_repo:
6+
type: boolean
7+
default: false
8+
run_id:
9+
type: string
10+
required: true
11+
ref:
12+
type: string
13+
required: true
14+
secrets:
15+
DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY:
16+
required: false
17+
RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY:
18+
required: false
19+
20+
jobs:
21+
publish-flatpak:
22+
name: Publish Flatpak
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: "Set up SSH Agent"
26+
shell: bash
27+
env:
28+
SSH_AUTH_SOCK: /tmp/ssh_agent.sock
29+
SSH_PRIVATE_KEY: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY }}
30+
SSH_HOST: downloads-hostgator.mixxx.org
31+
run: |
32+
ssh-agent -a $SSH_AUTH_SOCK > /dev/null
33+
ssh-add - <<< "${SSH_PRIVATE_KEY}"
34+
mkdir -p "${HOME}/.ssh"
35+
ssh-keyscan "${SSH_HOST}" >> "${HOME}/.ssh/known_hosts"
36+
echo "SSH_AUTH_SOCK=${SSH_AUTH_SOCK}" >> "${GITHUB_ENV}"
37+
38+
- name: Check out repository
39+
if: ${{ inputs.update_repo }}
40+
uses: actions/checkout@v6
41+
42+
- name: "Prepare"
43+
id: prepare
44+
shell: bash
45+
env:
46+
REF: ${{ inputs.ref }}
47+
run: |
48+
sudo apt-get update
49+
sudo apt-get install -y flatpak ostree
50+
# Download rsync wrapper to safely update ostree
51+
wget https://raw.githubusercontent.com/ostreedev/ostree-releng-scripts/621f7637ba6b8e0a8b761ce643c16a1511d04f6b/rsync-repos
52+
chmod +x rsync-repos
53+
54+
if [[ "$REF" =~ ^refs/tags/[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
55+
echo "commit_summary=Stable build for 2.5" >> $GITHUB_OUTPUT
56+
echo "branch=stable" >> $GITHUB_OUTPUT
57+
elif [ "$REF" = "refs/heads/2.6" ]; then
58+
echo "commit_summary=Beta build for 2.6" >> $GITHUB_OUTPUT
59+
echo "branch=beta" >> $GITHUB_OUTPUT
60+
echo "expiry=30 days" >> $GITHUB_OUTPUT
61+
elif [ "$REF" = "refs/heads/main" ]; then
62+
echo "commit_summary=Nightly build for 2.7" >> $GITHUB_OUTPUT
63+
echo "branch=nightly" >> $GITHUB_OUTPUT
64+
echo "expiry=14 days" >> $GITHUB_OUTPUT
65+
else
66+
echo "::error:: The git reference is unsupported for publication to the Flatpak repo."
67+
exit 1
68+
fi
69+
70+
- name: "Download bundles"
71+
env:
72+
GH_TOKEN: ${{ github.token }}
73+
RUN_ID: ${{ inputs.run_id }}
74+
shell: bash
75+
run: |
76+
gh --repo mixxxdj/mixxx run download $RUN_ID --pattern 'Flatpak *' -D bundles
77+
find bundles/ -name *.flatpak -exec mv {} bundles/ \;
78+
find bundles/ -mindepth 1 -type d -delete
79+
if [ ! `find bundles/ -name '*x86_64.flatpak' | wc -l` -eq 1 ]; then
80+
echo "At least a x86_64 build is expected. Current bundles:"
81+
find bundles/ -type f
82+
exit 1
83+
fi
84+
version=$(find bundles/ -name '*x86_64.flatpak' | cut -d- -f 2- | rev | cut -d- -f 2- | rev)
85+
echo "VERSION=${version}" >> $GITHUB_ENV
86+
87+
- name: "[Ubuntu] Import PPA GPG key"
88+
run: gpg --import <(echo "${RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY}")
89+
env:
90+
RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY: ${{ secrets.RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY }}
91+
92+
- name: "Import bundle to repo"
93+
env:
94+
GPG_KEY_ID: rryan@mixxx.org
95+
COMMIT_SUMMARY: ${{ steps.prepare.outputs.commit_summary }}
96+
BRANCH: ${{ steps.prepare.outputs.branch }}
97+
shell: bash
98+
run: |
99+
set -x
100+
101+
function import_to_repo {
102+
file=$1
103+
id=$2
104+
arch=$3
105+
type=$4
106+
107+
flatpak build-import-bundle -v --gpg-sign=$GPG_KEY_ID repo.tmp "$file"
108+
checksum=$(ostree --repo=repo.tmp rev-parse "${type}/${id}/${arch}/master")
109+
metadata=$(ostree --repo=repo.tmp show --print-metadata-key=xa.metadata "${type}/${id}/${arch}/master")
110+
ostree --repo=repo pull --depth=-1 --mirror "upstream:${type}/${id}/${arch}/${BRANCH}" || true
111+
ostree --repo=repo pull-local repo.tmp "${checksum}"
112+
ostree --repo=repo commit \
113+
--gpg-sign=$GPG_KEY_ID \
114+
-b "${type}/${id}/${arch}/${BRANCH}" \
115+
-s "$COMMIT_SUMMARY" \
116+
"--add-metadata-string=version=$VERSION" \
117+
"--add-metadata-string=xa.metadata=$(printf "%b" "${metadata:1:-1}")" \
118+
"--tree=ref=${checksum}"
119+
ostree --repo=repo show --print-metadata-key=xa.metadata "${type}/${id}/${arch}/${BRANCH}"
120+
}
121+
122+
# Prepare local repos
123+
ostree --repo=repo.tmp init --mode=archive-z2
124+
ostree --repo=repo init --mode=archive-z2
125+
126+
# Hook publish repo to the remote
127+
ostree --repo=repo remote add upstream https://downloads.mixxx.org/flatpak/
128+
129+
for arch in "x86_64" "aarch64"; do
130+
import_to_repo "bundles/Mixxx-${VERSION}-${arch}.flatpak" org.mixxx.Mixxx ${arch} app
131+
if [ -f "bundles/Mixxx-${VERSION}-${arch}.Debug.flatpak" ]; then
132+
import_to_repo "bundles/Mixxx-${VERSION}-${arch}.Debug.flatpak" org.mixxx.Mixxx.Debug ${arch} runtime
133+
else
134+
echo "No debug extension for ${arch}"
135+
fi
136+
done
137+
138+
- name: "Cleanup old builds"
139+
if: ${{ steps.prepare.outputs.expiry != null }}
140+
shell: bash
141+
env:
142+
EXPIRY: ${{ steps.prepare.outputs.expiry }}
143+
run: |
144+
ostree --repo=repo prune --refs-only --keep-younger-than="$EXPIRY ago"
145+
- name: "Push the updated repo"
146+
env:
147+
SSH_HOST: downloads-hostgator.mixxx.org
148+
SSH_USER: mixxx
149+
GPG_KEY_ID: rryan@mixxx.org
150+
shell: bash
151+
run: |
152+
ostree --repo=repo summary -u --gpg-sign=$GPG_KEY_ID
153+
flatpak build-update-repo --gpg-sign=$GPG_KEY_ID repo
154+
./rsync-repos --src "repo/" --dest "${SSH_USER}@${SSH_HOST}:public_html/downloads/flatpak" --rsync-opts "--verbose --recursive --checksum --times --delay-updates"
155+
156+
- name: "Update the repo manifest"
157+
if: ${{ inputs.update_repo }}
158+
env:
159+
SSH_HOST: downloads-hostgator.mixxx.org
160+
SSH_USER: mixxx
161+
shell: bash
162+
run: |
163+
rsync --verbose "packaging/flatpak/repo.flatpakrepo" "${SSH_USER}@${SSH_HOST}:public_html/downloads/flatpak/repo.flatpakrepo"
164+
165+
# TODO we could also publish a .flatpakref file to allow one-click install a version and publish this as a comment to the PR.

.github/workflows/release.yml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ on:
1111
- "[0-9].[0-9]-*"
1212
workflow_dispatch:
1313

14-
env:
15-
# This variable stores the map of Mixxx branches that still being developed. The key is the branch receiving support and the value is the next version in line
16-
# NOTE: this must be valid JSON!
17-
ACTIVE_VERSIONS: |-
18-
{"2.5": "2.6", "2.6": "main"}
19-
2014
# Global allowed scopes for all actions
2115
permissions:
2216
contents: write # to sync branches
@@ -48,6 +42,20 @@ jobs:
4842
NETLIFY_BUILD_HOOK: ${{ secrets.NETLIFY_BUILD_HOOK }}
4943
RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY: ${{ secrets.RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY }}
5044

45+
publish:
46+
needs:
47+
- build
48+
uses: ./.github/workflows/flatpak.yml
49+
# Flatpak repo only support stable (non-beta tag release), beta and alpha release publication
50+
if: ${{ (github.ref_type == "tag" && !contains('-', github.ref_name)) || github.ref_name == '2.6' || github.ref_name == 'main' }}
51+
with:
52+
ref: ${{ github.ref }}
53+
update_repo: ${{ github.ref_name == 'main' }}
54+
run_id: ${{ github.run_id }}
55+
secrets:
56+
DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY }}
57+
RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY: ${{ secrets.RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY }}
58+
5159
sync:
5260
if: ${{ github.ref != 'refs/heads/main' && github.repository == 'mixxxdj/mixxx' }}
5361
uses: ./.github/workflows/sync_branches.yml

packaging/flatpak/repo.flatpakrepo

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[Flatpak Repo]
2+
Title=Mixxx
3+
Url=https://downloads.mixxx.org/flatpak/
4+
Homepage=https://mixxx.org/
5+
Comment=Flatpak repo for Mixxx releases and snapshots
6+
Description=Flatpak repo for Mixxx releases and snapshots
7+
Icon=https://mixxx.org/theme/images/mixxx-logo.svg
8+
GPGKey=LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCkNvbW1lbnQ6IEhvc3RuYW1lOiAKVmVyc2lvbjogSG9ja2V5cHVjayAyLjIKCnhzRk5CRTFjeENzQkVBQzJaNE5wbnhJb0ZiYzV1NzJMV01WMEdtV1VJNm5PekZXUHdGUWNSalIzRTVIb2F2dmYKVSs3dS9QSkRrdnN5OWV3VEI0OEVFNXB4T0dFRHN4WWVKRnFmTWJoazJESFNlbkp4OGtvaUsrK0JJYk5PMEpLTQpHOVlEME9QTmZQZnA1UzJnY09Dc2k1cElrTkdQZjE5bWMyKytKVTN1emxMM1JjOE5sMG9JdklMSmxWVDhhT2RzCkJ1RC9OaHVrNlFGQ1UzbGYwdUpBaFA3QU1mSnRHeS9QYTJ4QlQ5bDBKdGJDZGhSWW4rSHNKclAwbkNqSUNYMDkKQ1A0cTVFMHBaNDVrSkFOa3ZEVEh3SCtqZDBWaXhxcTcyWVhRZ0MvOWlMMXpUNnhvUkx6aG9SSTNXQ1M3djhVRwppZk01TTVacGFQL3ozQjdDYWlqNHB1ZGlqVFRHeEkzamhFUm1BR3hNQzNxdG1Bd1Exc201SXM0aHZVT0RSOWtkCnMwL2RaZGVHUG0zSy8xazRNcVluVndtTHV1M0x4SGd2OXliUXpnemp5Um9GaytqMWZnbzU1N08zUWdsRDczWEwKQ043cUVpWFFtNEJKTzJ1Y0MxbEVva1NtY2ZtOURTdk9xZzlPZDdJek5CQ3VDU0VLRjBjTXdWMC80QnE2Z3NMWgpwekl5cGRtc05oT2txQ1B4d0RQRXIyMFBFQU5CQThUMVd2MDY0OGNrdGZtaFd2aDduYkRURndVUmZFRlU2Z2lIClZmL1lNUVdLOUxReDdSVE1YNHFxSVB2VktkNEZ2UmREZ2x4QzloTnVxTWFucFQwb2RCTEI4WktnOHNDU05yTUQKQnhOU0ZvaGtSZmJBUkYyYldoRk5EcTExSzhGOTJHY1IrNFNlUU9NR2NJZHYzanZvbkRHYVRFRm13d0FSQVFBQgp6UmxTU2lCU2VXRnVJRHh5Y25saGJrQnRhWGg0ZUM1dmNtYyt3c0Y0QkJNQkFnQWlCUUpOWE1RckFoc0RCZ3NKCkNBY0RBZ1lWQ0FJSkNnc0VGZ0lEQVFJZUFRSVhnQUFLQ1JCdmNKR1UyU3hKUjYrTUVBQ09vcUxlWnhNQ0xTY3UKcFdmTGRyczVibDg2QzlRODlXeDFzeWMwcEFVc2tlU1o2SzFmZHJtQWE0Um9EeGsxYWx0L1hReFFQNE5IZ0ZXTApCTWVOQS82Uk44bHczTXZudVNPR2ozcHFkNEtoamswYTczRUt3REpXYWU1cGdKNnIxL0g1clVlOUlFVDRpTWpxCmh0V253c0dqWTdTOEhtKzRsaGtlbXhicmM3M1ZQb2E3S2x4cFVzdHVPSDFzSHh0aDkxZDlrazN6c2dHVEd2a2kKRTl2M1llWkYvcWRSNURhcDFwTElrWVg2VGpjMkIwekxMbXRoMTd4Tk1lUVhGL3pYNXZadnhGM3ZGODJFMEIvYQowNWFZUHUzc1hqSmpYcVd5UmxteFozRnZZdzB5TVZ3SEVRSkNyL3JkakZGL2liQW9XTGVJb1h6ZG1YRDR6OFpaCkw5eDdiVDhrdmFYWFFNbFVYWEdIQXRYVHRCTkNqSkNjR0xjc0c1RjVtUnVPb2toTHJkQ2l0K2VwdGJja2FZWHIKdmdzUlZDSXcwdnJUME9BMFlUTEVCZk9BbXBZWDI5ZDZjSHhLWVRWcW9WRVhaMzVMaE92STFGYk1sRXpiUVdyMQpIVGRMaUt3L1JPYWhGRmJTclNSS0tRUWFWV0EvSTJmQjIwdmhycys5WWFJVjFVVysrNTYyRC9IeElyZVFjeWdKCk9DVktZcTJjTndkVExPK2lWTXJxUk9TWDRuTE9TSkRpWkd1UmtDNUI3OVoxcjVGWXNoL2RJTlhrZ29PaldGdzIKZU8zcmNwZjBwWFMvUlFpajRsL1dMa01NTGFmcjUxZS9HSW53dGIvZm5oNHMxaVBZeUpXalpSSVRSYk1jRnZaSApMc3BiREw3SVVyaVQyVVhvRy9PYjVxd2lCNlZBZnM3QlRRUk5YTVFyQVJBQTdKTGhhV2VmR25SZVJJQlBGell0ClNod0kxS1l2MFFvRkhkRVpIZ2Z0aWxVNENkbmdHZ0xwcVVoeW03eWpYU3NRMmFaVXZrTExkcy9JeHZ2QWxsbnUKSWE5Q0Nzc242NjRtL0lXaGFRZVZrQ1BqaXBvTk8xWlRrQURLUkVzVHpOZ3c0TDdMVmQ4ZFNYc2h2TzdKc25zVgpIWkxrN3J4STdoSnRoK2xoRTVZUGVDVHBWNENPUzRMdG5Tc09MM28wekpmZGQ1Z0grY2J1VkxBSzFPalpFVExrCmIyMk1wOWRPQ1lzMFNNcUFMU2hXYkt1M085Mk1SeXczaFM5enBsa2poK0p2RU9pN1RLOGFOdVNYWFRsWHJxeEMKUUw3YXFiWE91S0xoZHBsMTVDdjdVUDRJSzY5UGpJWnArbzMraHpyajh1blJtaVduSnl5bkxFbUZQcWpHL3FrRQpZSGo3bEEvaTlUTzd1U0NUanFnb3NZM2dsM0JZSXQ4b0F6WGhGZjNSOWx5cEFQV29SeDA4YWF6WU9mS1lDNTNUCmpZSXhMT2orbTVrNnVsOUhNaHpjb2lWbWlHbDZlYW9OWGhaZlAvUFgvQlFncXRHL3RDTE9mVC9KWERNN0oxZFcKUFlXYktmeU9aRjlPcTNRU2ZpQkRRWXpLLzBYK0dYdTJodTg2TUxNanFReERueU55SDZHRWwwRmVsdHVWVFdHRAp2VnRsVkZjQ3YxOTIxdlNQUGhFc25jMFB1N0tObkJwNk1rVlpmMFZzdEVrSUwrV3lNeTRUQVdkUDJaeUVRdWh5CmN2RGE1RUtQaGNVWVM1SlBVbnR5b2U5THBkMmFVNDNyYjNneW95U1I2WlRxUUt5WnRtb0pTLzY5VXI5SWdZRCsKYm1pakNoZm5FTWlNdHBrd1lodlVqTjBBRVFFQUFjTEJYd1FZQVFJQUNRVUNUVnpFS3dJYkRBQUtDUkJ2Y0pHVQoyU3hKUjZQdEQvNHNKTzcydWszVjE3WDlscHo1THppeVlIcHVpTG1KZlFIZEE5aDYvYjI1dWg2cGFxV1EzSmdOCnY1N0RZR2RSdVR4NnREUUtVZFc4UlJOSGpqR2dGSFo5bHpOMVl0Q0lzb240RDF3QzkwSEJ3WVpJeTNHL2M2c08KTkdoUkhhb2Q3cjVNMGllOWZ4L3VTZkVaNGlESnBPUExsbE5KR3g2UlhZdFNSVFZMTlNiY0FvZVV0TW1aL1U0Wgp1ZDdnamlKWkpIOHdtWDZKUGkxbk5SdnlPcm54Q0hudTcvQ2l1SW8rT1M3ZXF6cHNvTDg4eU5rYlA5d3kxN1JsCkYyeW9pVmtPK0N4Mi9EZXdWWXdGQWpQY2RlRlp1REliZ2JWNzFLSDN4OWw3ejVESnpkMjhWdUkxK1VqNFJMekQKcGN1N0l0NGJNMnBoNzhSUlJEdjFrNFJMa1pjb2liMytLamIwbFhQMC9MSjgwRHluamxCaE5raS9qSExDWnFaMQpSRWhrcDB2Rzdlc25ZQWJtK0JHNjFvcm9XUUZ3QkZMVmpqSFNja1dtVk9OS2VuTWlSbXdZOGN5VDhyZjRhMlVXCktkVnJteWxQQVV6MEd3TFZrOGsxWkZxK0ZpUjRmd0F3T3ZweGpCY1VETVE5bG5CWjBRL2R6VU96RktaSStuK2wKNGFPYStZb1hBQlVPTGprVGNvMmQrUjlFb2tPV1kzQk0xTUZXU2l2WDlSRXJFZGFXNXN1ak5yS1JIMksyOHR2aQp3T1d3Z2N5RWFucGcyUzBWMU1SNHlTRFp3RHcxaG1Ib1F3OE5Jd1BJcWtHUmJaSlIwQ3J0Y3ZBekpMa2VQcW4vCk1zQ1YzN0RDUCtrVlNtY0RWcU5vcGYwclFNcFpLK3MvblhKS2RIVGJGdVFqd29DWUl1NENsZz09Cj1IaHY0Ci0tLS0tRU5EIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0K

0 commit comments

Comments
 (0)