name: Release on: push: tags: - 'v*' permissions: contents: write jobs: release: name: Build & publish plugin zip runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Build plugin zip working-directory: ${{ github.workspace }} run: | set -euo pipefail VERSION="${GITHUB_REF_NAME#v}" OUT="dist/projects-portfolio-v${VERSION}.zip" rm -rf dist mkdir -p dist # Use Python's stdlib zipfile module — guaranteed to be on ubuntu-latest. python3 - "$OUT" <<'PYEOF' import os import sys import zipfile out_path = sys.argv[1] allowed = [ "projects-portfolio.php", "README.md", "LICENSE", "admin", "assets", "includes", "languages", "templates", ] with zipfile.ZipFile(out_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: for entry in allowed: if os.path.isdir(entry): for root, _, files in os.walk(entry): for name in files: abs_path = os.path.join(root, name) arcname = os.path.join("projects-portfolio", abs_path) zf.write(abs_path, arcname) elif os.path.isfile(entry): zf.write(entry, os.path.join("projects-portfolio", entry)) else: sys.exit(f"Allowlisted path missing: {entry}") PYEOF echo "Built $OUT" python3 -c "import zipfile; zf=zipfile.ZipFile('$OUT'); print('\n'.join(zf.namelist()))" - name: Upload artifact uses: actions/upload-artifact@v3 with: name: projects-portfolio-${{ github.ref_name }} path: dist/projects-portfolio-*.zip if-no-files-found: error - name: Create release env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} REPO: ${{ github.repository }} TAG: ${{ github.ref_name }} run: | set -euo pipefail if [ -z "${GITEA_TOKEN:-}" ]; then echo "::error::GITEA_TOKEN secret is not set. Create a personal access token in Gitea with 'write:repository' scope and add it as a repository secret named GITEA_TOKEN." >&2 exit 1 fi API="https://git.keithsolomon.net/api/v1" # Build the JSON payload with python (no jq dependency). payload=$(TAG="$TAG" python3 -c ' import json, os, sys tag = os.environ["TAG"] body = ( "Automated release.\n\n" "Built from commit " + os.environ.get("GITHUB_SHA", "unknown") + ".\n\n" "See the workflow run for the artifact." ) print(json.dumps({ "tag_name": tag, "name": tag, "body": body, "draft": False, "prerelease": False, })) ') # 1. Create the release (Gitea doesn't auto-generate notes). release_json=$(curl -fsS -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "$payload" \ "${API}/repos/${REPO}/releases") # 2. Extract the release id (Gitea returns the full release object). release_id=$(TAG="$TAG" python3 -c ' import json, sys data = json.loads(sys.stdin.read()) print(data.get("id", "")) ' <<<"$release_json") if [ -z "$release_id" ]; then echo "::error::Failed to create release. Response: $release_json" >&2 exit 1 fi echo "Created release id=$release_id" # 3. Upload the zip as a release asset. zip_path=( dist/projects-portfolio-*.zip ) zip_path="${zip_path[0]}" curl -fsS -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/zip" \ --data-binary "@${zip_path}" \ "${API}/repos/${REPO}/releases/${release_id}/assets?name=$(basename "$zip_path")" echo "Uploaded asset: $(basename "$zip_path")"