name: release # Push a tag matching vX.Y.Z (e.g. v1.2.3) to build and publish a release. # The tag drives the version — nothing to bump in source files beforehand. on: push: tags: - "v[0-9]+.[0-9]+.[0-9]+" jobs: build: # Needed to create the release and upload assets with GITEA_TOKEN below, # regardless of this instance's default Actions permission mode. permissions: contents: write # Runner defaults `run:` steps to `sh`, which doesn't understand # `set -o pipefail` used below — force bash explicitly. defaults: run: shell: bash # Must match a label your act_runner is registered with. The runner's # own default label-image is irrelevant here since `container:` below # overrides the actual build image per-job. runs-on: ubuntu-latest container: # :latest — always the most recently pushed build-image.sh output. # Pin to a specific tag here (see build-image/VERSION) if you need a # release build to be reproducible against an exact toolchain image. image: cr.ladkau.de/schwert-und-magie/builder:latest # Lets the runner pull a private image without a manual `docker login` # on the runner host — see docs/publish.md §4.3. credentials: username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASSWORD }} steps: - uses: actions/checkout@v4 - name: Write release signing credentials run: | set -euo pipefail echo "${{ secrets.RELEASE_KEYSTORE_B64 }}" | base64 -d \ > SchwertUndMagieOnPebbleCompanionApp/release.keystore printf '%s\n' "${{ secrets.RELEASE_KEYSTORE_PROPERTIES }}" \ > SchwertUndMagieOnPebbleCompanionApp/keystore.properties - name: Build artifacts run: | set -euo pipefail VERSION="${{ gitea.ref_name }}" VERSION="${VERSION#v}" VERSION="$VERSION" ./dist.sh - name: Create release and upload artifacts run: | set -euo pipefail API="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}" AUTH="Authorization: token ${{ secrets.GITEA_TOKEN }}" TAG="${{ gitea.ref_name }}" # Reuse an existing release for this tag instead of failing outright # (curl -f exit 22) if a prior run already created it — e.g. a retry # after a later step failed. (No -f here: a 404 for "no release yet" # is expected, not an error — it just leaves .id empty below.) RELEASE_ID="$(curl -s "$API/releases/tags/$TAG" -H "$AUTH" | jq -r '.id // empty')" if [ -z "$RELEASE_ID" ]; then RELEASE_ID="$(curl -sf -X POST "$API/releases" \ -H "$AUTH" -H "Content-Type: application/json" \ -d "{\"tag_name\": \"$TAG\", \"name\": \"$TAG\"}" \ | jq -r .id)" fi for f in dist/*; do NAME="$(basename "$f")" # Same idempotency concern for assets: a retry re-uploading a name # that's already attached would 409, so replace it instead. EXISTING_ID="$(curl -sf "$API/releases/$RELEASE_ID/assets" -H "$AUTH" \ | jq -r --arg n "$NAME" '.[] | select(.name == $n) | .id')" if [ -n "$EXISTING_ID" ]; then curl -sf -X DELETE "$API/releases/$RELEASE_ID/assets/$EXISTING_ID" -H "$AUTH" fi curl -sf -X POST "$API/releases/$RELEASE_ID/assets?name=$NAME" \ -H "$AUTH" -F "attachment=@$f" done - name: Publish to dl.ladkau.de run: | set -euo pipefail mkdir -p ~/.ssh echo "${{ secrets.DL_SFTP_KEY }}" > ~/.ssh/dl_sftp_key chmod 600 ~/.ssh/dl_sftp_key BATCH="$(mktemp)" { echo "-mkdir files/schwert-und-magie" for f in dist/*; do echo "put $f files/schwert-und-magie/$(basename "$f")" done } > "$BATCH" sftp -i ~/.ssh/dl_sftp_key -P 2223 \ -o StrictHostKeyChecking=accept-new \ -b "$BATCH" uploader@dl.ladkau.de