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: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} REPO: ${{ github.repository }} TAG: ${{ github.ref_name }} GH_API_URL: ${{ github.api_url }} run: | set -euo pipefail # Branch on host: github.com sets GITHUB_API_URL; Gitea leaves it empty # (or set to the Gitea base, which we detect by path). We treat any # api_url that is the github.com default as GitHub and anything else as Gitea. zip_path=( dist/projects-portfolio-*.zip ) zip_path="${zip_path[0]}" asset_name=$(basename "$zip_path") asset_bytes=$(wc -c < "$zip_path") if [[ "$GH_API_URL" == "https://api.github.com" ]]; then # ---- GitHub.com path ---- if [ -z "${GITHUB_TOKEN:-}" ]; then echo "::error::GITHUB_TOKEN is not available on this runner. Check repo permissions." >&2 exit 1 fi payload=$(TAG="$TAG" GH_SHA="$GITHUB_SHA" python3 - <<'PYEOF' import json, os print(json.dumps({ "tag_name": os.environ["TAG"], "name": os.environ["TAG"], "body": ( "Automated release.\n\n" "Built from commit " + os.environ.get("GH_SHA", "unknown") + ".\n\n" "See the workflow run for the artifact." ), "draft": False, "prerelease": False, "generate_release_notes": True, })) PYEOF ) release_json=$(curl -fsS -X POST \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Accept: application/vnd.github+json" \ -H "Content-Type: application/json" \ -d "$payload" \ "${GH_API_URL}/repos/${REPO}/releases") release_id=$(python3 -c 'import json,sys; print(json.loads(sys.stdin.read())["id"])' <<<"$release_json") upload_url=$(python3 -c 'import json,sys; print(json.loads(sys.stdin.read())["upload_url"])' <<<"$release_json") echo "Created GitHub release id=$release_id" # Asset upload uses the per-release upload_url (template with {?name,label}). curl -fsS -X POST \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Accept: application/vnd.github+json" \ -H "Content-Type: application/zip" \ --data-binary "@${zip_path}" \ "${upload_url}?name=${asset_name}" echo "Uploaded GitHub asset: ${asset_name}" else # ---- Gitea path ---- 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 # Gitea's api_url may be unset or set to the Gitea base. if [ -z "${GH_API_URL:-}" ] || [[ "$GH_API_URL" == "https://git.keithsolomon.net"* ]]; then API="https://git.keithsolomon.net/api/v1" else API="${GH_API_URL%/}/api/v1" fi payload=$(TAG="$TAG" GH_SHA="$GITHUB_SHA" python3 - <<'PYEOF' import json, os print(json.dumps({ "tag_name": os.environ["TAG"], "name": os.environ["TAG"], "body": ( "Automated release.\n\n" "Built from commit " + os.environ.get("GH_SHA", "unknown") + ".\n\n" "See the workflow run for the artifact." ), "draft": False, "prerelease": False, })) PYEOF ) release_json=$(curl -fsS -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "$payload" \ "${API}/repos/${REPO}/releases") release_id=$(python3 -c 'import json,sys; print(json.loads(sys.stdin.read())["id"])' <<<"$release_json") if [ -z "$release_id" ]; then echo "::error::Failed to create Gitea release. Response: $release_json" >&2 exit 1 fi echo "Created Gitea release id=$release_id" 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=${asset_name}" echo "Uploaded Gitea asset: ${asset_name}" fi