Some checks failed
Lint & Test / test (push) Failing after 30s
release.yml: add fallback for existing releases on tag re-push. installer.nsi: add .onInit file lock check, use LaunchApp function instead of RUN_PARAMETERS to fix NSIS quoting bug. build-dist.ps1: copy start-hidden.vbs to dist scripts/. start-hidden.vbs: embedded Python fallback for installed/dev envs. Update ci-cd.md with version detection, NSIS best practices, local build testing, Gitea vs GitHub differences, troubleshooting. Update frontend.md with full entity type checklist and common pitfalls.
273 lines
9.4 KiB
YAML
273 lines
9.4 KiB
YAML
name: Build Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
jobs:
|
|
# ── Create the release first (shared by all build jobs) ────
|
|
create-release:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
release_id: ${{ steps.create.outputs.release_id }}
|
|
steps:
|
|
- name: Create Gitea release
|
|
id: create
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
run: |
|
|
TAG="${{ gitea.ref_name }}"
|
|
BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}"
|
|
|
|
IS_PRE="false"
|
|
if echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
|
|
IS_PRE="true"
|
|
fi
|
|
|
|
# Build registry path for Docker instructions
|
|
SERVER_HOST=$(echo "${{ gitea.server_url }}" | sed -E 's|https?://||')
|
|
REPO=$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')
|
|
DOCKER_IMAGE="${SERVER_HOST}/${REPO}"
|
|
|
|
# Build release body via Python to avoid YAML escaping issues
|
|
BODY_JSON=$(python3 -c "
|
|
import json, sys
|
|
tag = '$TAG'
|
|
image = '$DOCKER_IMAGE'
|
|
body = f'''## Downloads
|
|
|
|
| Platform | File | Description |
|
|
|----------|------|-------------|
|
|
| Windows (installer) | \`LedGrab-{tag}-setup.exe\` | Install with Start Menu shortcut, optional autostart, uninstaller |
|
|
| Windows (portable) | \`LedGrab-{tag}-win-x64.zip\` | Unzip anywhere, run LedGrab.bat |
|
|
| Linux | \`LedGrab-{tag}-linux-x64.tar.gz\` | Extract, run ./run.sh |
|
|
| Docker | See below | docker pull + docker run |
|
|
|
|
After starting, open **http://localhost:8080** in your browser.
|
|
|
|
### Docker
|
|
|
|
\`\`\`bash
|
|
docker pull {image}:{tag}
|
|
docker run -d --name ledgrab -p 8080:8080 -v ledgrab-data:/app/data {image}:{tag}
|
|
\`\`\`
|
|
|
|
### First-time setup
|
|
|
|
1. Change the default API key in config/default_config.yaml
|
|
2. Open http://localhost:8080 and discover your WLED devices
|
|
3. See INSTALLATION.md for detailed configuration
|
|
'''
|
|
import textwrap
|
|
print(json.dumps(textwrap.dedent(body).strip()))
|
|
")
|
|
|
|
RELEASE=$(curl -s -X POST "$BASE_URL/releases" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"tag_name\": \"$TAG\",
|
|
\"name\": \"LedGrab $TAG\",
|
|
\"body\": $BODY_JSON,
|
|
\"draft\": false,
|
|
\"prerelease\": $IS_PRE
|
|
}")
|
|
|
|
# Fallback: if release already exists for this tag, fetch it instead
|
|
RELEASE_ID=$(echo "$RELEASE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null)
|
|
if [ -z "$RELEASE_ID" ]; then
|
|
echo "::warning::Release already exists for tag $TAG — reusing existing release"
|
|
RELEASE=$(curl -s "$BASE_URL/releases/tags/$TAG" \
|
|
-H "Authorization: token $GITEA_TOKEN")
|
|
RELEASE_ID=$(echo "$RELEASE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
|
fi
|
|
echo "release_id=$RELEASE_ID" >> "$GITHUB_OUTPUT"
|
|
echo "Release ID: $RELEASE_ID"
|
|
|
|
# ── Windows portable ZIP (cross-built from Linux) ─────────
|
|
build-windows:
|
|
needs: create-release
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Install system dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends zip libportaudio2 nsis msitools
|
|
|
|
- name: Cross-build Windows distribution
|
|
run: |
|
|
chmod +x build-dist-windows.sh
|
|
./build-dist-windows.sh "${{ gitea.ref_name }}"
|
|
|
|
- name: Upload build artifacts
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: LedGrab-${{ gitea.ref_name }}-win-x64
|
|
path: |
|
|
build/LedGrab-*.zip
|
|
build/LedGrab-*-setup.exe
|
|
retention-days: 90
|
|
|
|
- name: Attach assets to release
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
run: |
|
|
RELEASE_ID="${{ needs.create-release.outputs.release_id }}"
|
|
BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}"
|
|
|
|
# Upload ZIP
|
|
ZIP_FILE=$(ls build/LedGrab-*.zip | head -1)
|
|
if [ -f "$ZIP_FILE" ]; then
|
|
curl -s -X POST \
|
|
"$BASE_URL/releases/$RELEASE_ID/assets?name=$(basename "$ZIP_FILE")" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/octet-stream" \
|
|
--data-binary "@$ZIP_FILE"
|
|
echo "Uploaded: $(basename "$ZIP_FILE")"
|
|
fi
|
|
|
|
# Upload installer
|
|
SETUP_FILE=$(ls build/LedGrab-*-setup.exe 2>/dev/null | head -1)
|
|
if [ -f "$SETUP_FILE" ]; then
|
|
curl -s -X POST \
|
|
"$BASE_URL/releases/$RELEASE_ID/assets?name=$(basename "$SETUP_FILE")" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/octet-stream" \
|
|
--data-binary "@$SETUP_FILE"
|
|
echo "Uploaded: $(basename "$SETUP_FILE")"
|
|
fi
|
|
|
|
# ── Linux tarball ──────────────────────────────────────────
|
|
build-linux:
|
|
needs: create-release
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Install system dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends libportaudio2
|
|
|
|
- name: Build Linux distribution
|
|
run: |
|
|
chmod +x build-dist.sh
|
|
./build-dist.sh "${{ gitea.ref_name }}"
|
|
|
|
- name: Upload build artifact
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: LedGrab-${{ gitea.ref_name }}-linux-x64
|
|
path: build/LedGrab-*.tar.gz
|
|
retention-days: 90
|
|
|
|
- name: Attach tarball to release
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
run: |
|
|
TAG="${{ gitea.ref_name }}"
|
|
RELEASE_ID="${{ needs.create-release.outputs.release_id }}"
|
|
BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}"
|
|
TAR_FILE=$(ls build/LedGrab-*.tar.gz | head -1)
|
|
TAR_NAME=$(basename "$TAR_FILE")
|
|
|
|
curl -s -X POST \
|
|
"$BASE_URL/releases/$RELEASE_ID/assets?name=$TAR_NAME" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/octet-stream" \
|
|
--data-binary "@$TAR_FILE"
|
|
|
|
echo "Uploaded: $TAR_NAME"
|
|
|
|
# ── Docker image ───────────────────────────────────────────
|
|
build-docker:
|
|
needs: create-release
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Extract version metadata
|
|
id: meta
|
|
run: |
|
|
TAG="${{ gitea.ref_name }}"
|
|
VERSION="${TAG#v}"
|
|
# Strip protocol and lowercase for Docker registry path
|
|
SERVER_HOST=$(echo "${{ gitea.server_url }}" | sed -E 's|https?://||')
|
|
REPO=$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')
|
|
REGISTRY="${SERVER_HOST}/${REPO}"
|
|
|
|
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
echo "registry=$REGISTRY" >> "$GITHUB_OUTPUT"
|
|
echo "server_host=$SERVER_HOST" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Login to Gitea Container Registry
|
|
id: docker-login
|
|
continue-on-error: true
|
|
run: |
|
|
echo "${{ secrets.GITEA_TOKEN }}" | docker login \
|
|
"${{ steps.meta.outputs.server_host }}" \
|
|
-u "${{ gitea.actor }}" --password-stdin
|
|
|
|
- name: Build Docker image
|
|
if: steps.docker-login.outcome == 'success'
|
|
run: |
|
|
TAG="${{ gitea.ref_name }}"
|
|
REGISTRY="${{ steps.meta.outputs.registry }}"
|
|
|
|
docker build \
|
|
--label "org.opencontainers.image.version=${{ steps.meta.outputs.version }}" \
|
|
--label "org.opencontainers.image.revision=${{ gitea.sha }}" \
|
|
-t "$REGISTRY:$TAG" \
|
|
-t "$REGISTRY:${{ steps.meta.outputs.version }}" \
|
|
./server
|
|
|
|
# Tag as latest only for stable releases
|
|
if ! echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
|
|
docker tag "$REGISTRY:$TAG" "$REGISTRY:latest"
|
|
fi
|
|
|
|
- name: Push Docker image
|
|
if: steps.docker-login.outcome == 'success'
|
|
run: |
|
|
TAG="${{ gitea.ref_name }}"
|
|
REGISTRY="${{ steps.meta.outputs.registry }}"
|
|
|
|
docker push "$REGISTRY:$TAG"
|
|
docker push "$REGISTRY:${{ steps.meta.outputs.version }}"
|
|
|
|
if ! echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
|
|
docker push "$REGISTRY:latest"
|
|
fi
|