name: Create Release on: push: tags: - "v*" jobs: release: runs-on: shell steps: - name: Build & release env: VERSION: ${{ gitea.ref_name }} GITEA_API: ${{ gitea.api_url }} GITEA_REPO: ${{ gitea.repository }} run: | set -e LOCAL="/var/www/atom-nexst" # Shallow clone for build SRC="/tmp/epicnext-release" rm -rf "$SRC" git clone --branch "${VERSION}" --depth 1 \ /docker/gitea/gitea/git/repositories/remco/epicnext-cms.git \ "$SRC" if [ -f /var/www/atom-nexst/.env ]; then cp /var/www/atom-nexst/.env "$SRC/.env" fi cd "$SRC" pnpm install --frozen-lockfile pnpm prisma:generate export SKIP_ENV_VALIDATION=1 pnpm build # Create release — Python reads changelog directly from git python3 << 'PYEOF' import json, os, subprocess, urllib.request, urllib.error version = os.environ["VERSION"] api = os.environ["GITEA_API"] repo = os.environ["GITEA_REPO"] token = "${{ secrets.GITEA_TOKEN }}" local = "/var/www/atom-nexst" # Get previous tag tags = subprocess.run( ["git", "-C", local, "tag", "--sort=-creatordate"], capture_output=True, text=True, check=False, ).stdout.strip().split("\n") tags = [t for t in tags if t] prev_tag = tags[1] if len(tags) > 1 else "" print(f"Tags: {tags}") print(f"Version: {version}, Previous: {prev_tag}") if prev_tag and prev_tag != version: r = subprocess.run( ["git", "-C", local, "log", "--oneline", "--no-decorate", f"{prev_tag}..{version}"], capture_output=True, text=True, check=False, ) notes_raw = r.stdout.strip() print(f"Range: {prev_tag}..{version}, stderr: {r.stderr.strip()}") else: r = subprocess.run( ["git", "-C", local, "log", "--oneline", "--no-decorate", version], capture_output=True, text=True, check=False, ) notes_raw = r.stdout.strip() print(f"Single tag {version}, stderr: {r.stderr.strip()}") if not notes_raw: notes_raw = "Initial release" print(f"Notes ({len(notes_raw)} chars):") print(notes_raw) print("=== End notes ===") body = f"""## EpicNext-CMS {version} ### Changes {notes_raw} --- *Automated release from Gitea Actions* """ payload = json.dumps({ "tag_name": version, "name": version, "body": body, "draft": False, "prerelease": False, }).encode("utf-8") def api_call(method, path, data=None): url = f"{api}/repos/{repo}/{path}" print(f"API {method} {url}") req = urllib.request.Request( url, data=data, headers={ "Authorization": f"token {token}", "Content-Type": "application/json", }, method=method, ) resp = urllib.request.urlopen(req) return json.loads(resp.read().decode("utf-8")) try: result = api_call("POST", "releases", payload) print(f"Release created: {result.get('html_url', result.get('id', '?'))}") except urllib.error.HTTPError as e: err_body = e.read().decode("utf-8") print(f"POST error {e.code}: {err_body}") if e.code == 409: releases = api_call("GET", "releases") for rel in releases: if rel["tag_name"] == version: result = api_call("PATCH", f"releases/{rel['id']}", payload) print(f"Release updated: {result.get('html_url', result.get('id', '?'))}") break else: print(f"ERROR: no existing release found for {version}") raise else: raise PYEOF