feat(snap): Snap Store packaging for Open CAD Studio
Repackages the released Linux AppImage (--appimage-extract) instead of rebuilding from source, triggered on completion of the "Release" workflow. Publishing to the Snap Store only happens once SNAPCRAFT_STORE_CREDENTIALS is set as a repo secret. Different from the other OpenAEC snaps in one important way: OCS uses winit + wgpu (Vulkan/GL), not GTK/WebKit, so this uses explicit opengl/wayland/x11 plugs and staged Mesa/X11/Wayland runtime libraries instead of the `gnome` extension. Higher confidence in the packaging mechanics (build succeeds, produces a valid .snap) than in the actual runtime GPU/windowing behavior under strict confinement, which needs real hands-on testing on a Linux desktop before publishing to stable -- see the PR description. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
c9c3d3b1bf
commit
00952d1996
2 changed files with 253 additions and 0 deletions
169
.github/workflows/snap.yml
vendored
Normal file
169
.github/workflows/snap.yml
vendored
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
name: Build Snap Package
|
||||
|
||||
on:
|
||||
# workflow_run werkt alleen als dit workflowbestand op de DEFAULT branch staat.
|
||||
# De workflow wordt getriggerd zodra "Release" afrondt (die triggert zelf op
|
||||
# `release: published` + workflow_dispatch, niet op elke main-push).
|
||||
workflow_run:
|
||||
workflows: ["Release"]
|
||||
types: [completed]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Bestaande release-tag om tegen te bouwen (test)'
|
||||
required: true
|
||||
default: 'v0.9.0'
|
||||
|
||||
# Minimale default; de build-snap-job zet zelf `contents: write` omdat hij de
|
||||
# snap als asset aan de release hangt.
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Eén globale groep, NIET annuleren: twee releases kort na elkaar publiceren
|
||||
# allebei naar het `stable`-kanaal van de Snap Store, en een Snap-release is
|
||||
# niet in te trekken.
|
||||
concurrency:
|
||||
group: snap
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build-snap:
|
||||
timeout-minutes: 75
|
||||
runs-on: ubuntu-22.04
|
||||
# `types: [completed]` vuurt OOK als de release-workflow faalde of werd
|
||||
# geannuleerd; zonder deze gate zou een mislukte release alsnog een snap
|
||||
# bouwen. Geen extra head_branch-guard nodig zoals bij open-calc-studio:
|
||||
# "Release" triggert uitsluitend op `release: published` + workflow_dispatch,
|
||||
# nooit op een gewone main-push, dus er is geen vervuilingsscenario.
|
||||
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
# Job-level zodat de gated publish-stap er in `if:` naar kan verwijzen.
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
# Bij workflow_run checkt checkout standaard de DEFAULT BRANCH uit,
|
||||
# niet de tag/commit die de release-workflow bouwde — fout, want
|
||||
# snap/snapcraft.yaml moet van de gebouwde commit komen. Daarom
|
||||
# expliciet de head_sha van die workflow; voor workflow_dispatch
|
||||
# (geen workflow_run-event) valt die weg naar github.ref (de branch
|
||||
# waarop handmatig werd gedispatcht).
|
||||
ref: ${{ github.event.workflow_run.head_sha || github.ref }}
|
||||
|
||||
- name: Get version
|
||||
id: get-version
|
||||
env:
|
||||
# Niet-vertrouwde invoer via env, NOOIT rechtstreeks ${} in de shell.
|
||||
# GITHUB_*-namen zelf NIET zetten: gereserveerd en al aanwezig in de runner.
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
DISPATCH_VERSION: ${{ github.event.inputs.version }}
|
||||
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
|
||||
VERSION="$DISPATCH_VERSION"
|
||||
elif [ "$EVENT_NAME" = "workflow_run" ]; then
|
||||
# head_branch is voor een `release`-getriggerde workflow_run niet
|
||||
# betrouwbaar gegarandeerd de tagnaam (kan de default branch zijn) —
|
||||
# daarom altijd de laatste gepubliceerde release opzoeken i.p.v. op
|
||||
# head_branch te vertrouwen.
|
||||
if printf '%s' "$HEAD_BRANCH" | grep -qE '^v[0-9]'; then
|
||||
VERSION="$HEAD_BRANCH"
|
||||
else
|
||||
VERSION="$(gh release list --exclude-drafts --limit 1 --json tagName --jq '.[0].tagName // empty')"
|
||||
fi
|
||||
else
|
||||
VERSION=""
|
||||
fi
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "::error::Kon geen versie afleiden (event=$EVENT_NAME, head_branch=$HEAD_BRANCH)"
|
||||
exit 1
|
||||
fi
|
||||
# `version` en `version_number` gaan verderop een `sed`-VERVANGINGSPATROON
|
||||
# in, en een dispatch-input is vrije tekst — een '/' of '&' herschrijft dat
|
||||
# patroon, een nieuwe regel schrijft een tweede regel in $GITHUB_OUTPUT
|
||||
# (output-injectie). Whitelist: de `case` dekt de hele waarde (dus ook
|
||||
# nieuwe regels), de regex daarna de structuur.
|
||||
case "$VERSION" in
|
||||
*[!v0-9.]*)
|
||||
echo "::error::Versie bevat tekens buiten 'v', cijfers en punten." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if ! printf '%s' "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||
echo "::error::Versie '$VERSION' heeft niet de vorm vX.Y.Z." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "version_number=${VERSION#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# We bouwen de Rust-app NIET opnieuw: de snap herverpakt de AppImage van de
|
||||
# gepubliceerde GitHub-release (--appimage-extract i.p.v. dpkg-deb -x, want
|
||||
# dit project levert geen .deb).
|
||||
- name: Wait for release AppImage and download it
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
VERSION: ${{ steps.get-version.outputs.version }}
|
||||
run: |
|
||||
echo "Wachten op AppImage-asset van release $VERSION..."
|
||||
found=""
|
||||
for i in $(seq 1 10); do
|
||||
if gh release view "$VERSION" --json assets --jq '.assets[].name' 2>/dev/null | grep -q '\.AppImage$'; then
|
||||
found=1
|
||||
echo "AppImage-asset gevonden"
|
||||
break
|
||||
fi
|
||||
echo "nog geen AppImage-asset... (poging $i/10)"
|
||||
sleep 15
|
||||
done
|
||||
if [ -z "$found" ]; then
|
||||
echo "::error::AppImage-asset voor $VERSION verscheen niet op tijd"
|
||||
exit 1
|
||||
fi
|
||||
gh release download "$VERSION" -p '*.AppImage' --clobber --dir .
|
||||
appimage=$(ls *.AppImage | head -1)
|
||||
cp "$appimage" open-cad-studio.AppImage
|
||||
echo "Gebruik $appimage -> open-cad-studio.AppImage"
|
||||
|
||||
- name: Set version in snapcraft.yaml
|
||||
env:
|
||||
VERSION_NUMBER: ${{ steps.get-version.outputs.version_number }}
|
||||
run: |
|
||||
sed -i "s/^version: .*/version: '$VERSION_NUMBER'/" snap/snapcraft.yaml
|
||||
grep '^version:' snap/snapcraft.yaml
|
||||
|
||||
- name: Build snap
|
||||
uses: snapcore/action-build@v1
|
||||
id: snapcraft
|
||||
|
||||
# Echte release (via workflow_run): snap als asset aan de release hangen.
|
||||
- name: Upload snap to GitHub release
|
||||
if: github.event_name == 'workflow_run'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
VERSION: ${{ steps.get-version.outputs.version }}
|
||||
SNAP: ${{ steps.snapcraft.outputs.snap }}
|
||||
run: |
|
||||
gh release upload "$VERSION" "$SNAP" --clobber
|
||||
|
||||
# Handmatige test: snap als CI-artifact (de release NIET aanraken).
|
||||
- name: Upload snap as workflow artifact
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: open-cad-studio-snap
|
||||
path: ${{ steps.snapcraft.outputs.snap }}
|
||||
if-no-files-found: error
|
||||
|
||||
# Live publiceren naar de Snap Store: alleen op een echte release én pas
|
||||
# zodra het store-credentials-secret bestaat (eigenaar-stap) — én pas
|
||||
# zodra de naam `open-cad-studio` op snapcraft.io geregistreerd is.
|
||||
- name: Publish to Snap Store
|
||||
if: github.event_name == 'workflow_run' && env.SNAPCRAFT_STORE_CREDENTIALS != ''
|
||||
uses: snapcore/action-publish@v1
|
||||
with:
|
||||
snap: ${{ steps.snapcraft.outputs.snap }}
|
||||
release: stable
|
||||
Loading…
Reference in a new issue