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 }} GH_SHA: ${{ github.sha }} run: | set -euo pipefail zip_path=( dist/projects-portfolio-*.zip ) zip_path="${zip_path[0]}" asset_name=$(basename "$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=$(python3 scripts/release-helper.py build-payload --github) 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=$(echo "$release_json" | python3 scripts/release-helper.py extract-id) upload_url=$(echo "$release_json" | python3 scripts/release-helper.py extract-upload-url) echo "Created GitHub release id=$release_id" 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 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=$(python3 scripts/release-helper.py build-payload) release_json=$(curl -fsS -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "$payload" \ "${API}/repos/${REPO}/releases") release_id=$(echo "$release_json" | python3 scripts/release-helper.py extract-id) 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