1 parent
69933f37e5
commit
ea1a0c85a9
4 files changed
+134
No files matched your search
@@ -0,0 +1,25 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
||||||
|
|
||||||
|
# The app is static files, so a broken manifest or service worker only shows up on a phone.
|
||||||
|
- name: Manifest and scripts parse
|
||||||
|
run: |
|
||||||
|
node -e "JSON.parse(require('fs').readFileSync('public/manifest.webmanifest','utf8'))"
|
||||||
|
for f in public/*.js; do node --check "$f"; done
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
# Push a tag such as v0.2.0 to publish public/ as a release archive that can be
|
||||||
|
# unpacked into SANDBAR_APP_DIR or hosted on any static site:
|
||||||
|
# git tag -a v0.2.0 -m "remora v0.2.0" && git push origin v0.2.0
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v*']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # release notes come from the history since the previous tag
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
||||||
|
|
||||||
|
- name: Build release archive
|
||||||
|
run: |
|
||||||
|
mkdir -p dist
|
||||||
|
tar -C public -czf "dist/remora_${GITHUB_REF_NAME}.tar.gz" .
|
||||||
|
(cd public && zip -qr "../dist/remora_${GITHUB_REF_NAME}.zip" .)
|
||||||
|
(cd dist && sha256sum remora_* > SHA256SUMS)
|
||||||
|
|
||||||
|
# Optional secret RELEASE_TOKEN: an access token that can write releases, for
|
||||||
|
# servers where the automatic job token can't.
|
||||||
|
- name: Publish the release
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
run: sh deploy/publish-release.sh "${GITHUB_REF_NAME}"
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.env
|
.env
|
||||||
|
dist/
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Creates (or updates) the Gitea release for a tag and uploads what the release job packed.
|
||||||
|
#
|
||||||
|
# TOKEN=<access token that can write releases> deploy/publish-release.sh v0.2.0
|
||||||
|
#
|
||||||
|
# In Gitea Actions GITHUB_SERVER_URL and GITHUB_REPOSITORY are already set. Safe to
|
||||||
|
# re-run: an existing release is reused and assets with the same name are replaced.
|
||||||
|
set -eu
|
||||||
|
TAG=${1:?usage: publish-release.sh <tag>}
|
||||||
|
: "${TOKEN:?set TOKEN to a Gitea access token that can write releases}"
|
||||||
|
SERVER=${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://git.veillax.com}}
|
||||||
|
REPO=${GITHUB_REPOSITORY:-Veillax/remora}
|
||||||
|
API="$SERVER/api/v1/repos/$REPO"
|
||||||
|
AUTH="Authorization: token $TOKEN"
|
||||||
|
|
||||||
|
# a JSON helper without needing jq: any python will do
|
||||||
|
PY=python3
|
||||||
|
python3 -c 'pass' > /dev/null 2>&1 || PY=python
|
||||||
|
json() { "$PY" -c "$1"; }
|
||||||
|
|
||||||
|
# release notes: the commit subjects since the previous tag
|
||||||
|
prev=$(git describe --tags --abbrev=0 "$TAG^" 2>/dev/null || true)
|
||||||
|
if [ -n "$prev" ]; then
|
||||||
|
notes=$(git log --pretty='format:- %s' "$prev..$TAG")
|
||||||
|
else
|
||||||
|
notes=$(git log --pretty='format:- %s' "$TAG")
|
||||||
|
fi
|
||||||
|
prerelease=false
|
||||||
|
case "$TAG" in *-*) prerelease=true ;; esac
|
||||||
|
|
||||||
|
body=$(NOTES="$notes" TAG="$TAG" PRE="$prerelease" json '
|
||||||
|
import json, os
|
||||||
|
print(json.dumps({"tag_name": os.environ["TAG"], "name": os.environ["TAG"], "body": os.environ["NOTES"],
|
||||||
|
"draft": False, "prerelease": os.environ["PRE"] == "true"}))')
|
||||||
|
|
||||||
|
# reuse the release when a failed job is re-run
|
||||||
|
id=$(curl -fsS -H "$AUTH" "$API/releases/tags/$TAG" 2>/dev/null | json 'import sys, json; print(json.load(sys.stdin)["id"])' 2>/dev/null || true)
|
||||||
|
if [ -z "$id" ]; then
|
||||||
|
echo "creating release $TAG"
|
||||||
|
id=$(curl -fsS -X POST -H "$AUTH" -H 'Content-Type: application/json' -d "$body" "$API/releases" | json 'import sys, json; print(json.load(sys.stdin)["id"])')
|
||||||
|
else
|
||||||
|
echo "release $TAG already exists (id $id): replacing its files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# the ids of the release's assets with a given name (a failed upload can leave a partial one behind)
|
||||||
|
asset_ids() {
|
||||||
|
curl -fsS -H "$AUTH" "$API/releases/$id/assets" | "$PY" -c 'import sys, json
|
||||||
|
for a in json.load(sys.stdin):
|
||||||
|
if a["name"] == sys.argv[1]:
|
||||||
|
print(a["id"])' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
for f in dist/*.tar.gz dist/*.zip dist/SHA256SUMS; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
name=$(basename "$f")
|
||||||
|
n=1
|
||||||
|
while :; do
|
||||||
|
for aid in $(asset_ids "$name"); do
|
||||||
|
curl -fsS -X DELETE -H "$AUTH" "$API/releases/$id/assets/$aid" > /dev/null
|
||||||
|
done
|
||||||
|
echo "uploading $name (attempt $n)"
|
||||||
|
if curl -fsS --max-time 1200 -X POST -H "$AUTH" -F "attachment=@$f" "$API/releases/$id/assets?name=$name" > /dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# large uploads can hit a proxy timeout (HTTP 502); try again
|
||||||
|
[ "$n" -lt 5 ] || { echo "giving up on $name after $n attempts" >&2; exit 1; }
|
||||||
|
n=$((n + 1))
|
||||||
|
sleep $((n * 10))
|
||||||
|
done
|
||||||
|
done
|
||||||
|
echo "published $SERVER/$REPO/releases/tag/$TAG"
|
||||||
Reference in new issue
Block a user