ci: Use standalone release script to fix JSON escaping issues
All checks were successful
Build .deb Package / build-and-package (push) Successful in 2m10s
All checks were successful
Build .deb Package / build-and-package (push) Successful in 2m10s
- Shell/curl JSON escaping caused HTTP 422 errors - Created scripts/create-release.py for reliable Gitea release creation - Uses Python urllib for proper JSON handling and multipart upload - Supports GITEA_TOKEN/GITHUB_TOKEN env vars with fallback
This commit is contained in:
@ -149,29 +149,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
DEB_NAME=$(ls linux-patch-manager_*.deb)
|
DEB_NAME=$(ls linux-patch-manager_*.deb)
|
||||||
VERSION="${{ steps.version.outputs.version }}"
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
TOKEN="${GITHUB_TOKEN:-$GITEA_TOKEN}"
|
export GITEA_TOKEN="${GITHUB_TOKEN:-$GITEA_TOKEN}"
|
||||||
REF_NAME="${GITHUB_REF_NAME:-v${VERSION}}"
|
python3 scripts/create-release.py \
|
||||||
REPO="${GITHUB_REPOSITORY:-echo/linux_patch_manager}"
|
--tag "${GITHUB_REF_NAME:-v${VERSION}}" \
|
||||||
echo "Creating release for tag: ${REF_NAME} repo: ${REPO}"
|
--deb "${DEB_NAME}" \
|
||||||
echo "DEB: ${DEB_NAME}"
|
--version "${VERSION}"
|
||||||
# Create release via Gitea API
|
|
||||||
HTTP_CODE=$(curl -s -o release.json -w "%{http_code}" -X POST \
|
|
||||||
"http://192.168.2.189:3000/api/v1/repos/${REPO}/releases" \
|
|
||||||
-H "Authorization: token ${TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"tag_name\": \"${REF_NAME}\", \"title\": \"Release ${VERSION}\", \"body\": \"Automated build from tag ${REF_NAME}.\\n\\n## Installation\\n\\n\\\`\\\`\\\`bash\\nsudo apt install ./linux-patch-manager_${VERSION}-1_amd64.deb\\n\\\`\\\`\\\`\\\"}")
|
|
||||||
echo "Release API HTTP status: ${HTTP_CODE}"
|
|
||||||
cat release.json
|
|
||||||
if [ "${HTTP_CODE}" != "201" ]; then
|
|
||||||
echo "ERROR: Failed to create release (HTTP ${HTTP_CODE})"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Extract release ID and upload .deb
|
|
||||||
RELEASE_ID=$(python3 -c "import json; print(json.load(open('release.json'))['id'])")
|
|
||||||
echo "Release ID: ${RELEASE_ID}"
|
|
||||||
curl -s -X POST \
|
|
||||||
"http://192.168.2.189:3000/api/v1/repos/${REPO}/releases/${RELEASE_ID}/assets" \
|
|
||||||
-H "Authorization: token ${TOKEN}" \
|
|
||||||
-F "attachment=@${DEB_NAME}" \
|
|
||||||
-F "name=${DEB_NAME}"
|
|
||||||
echo "Release upload complete"
|
|
||||||
|
|||||||
117
scripts/create-release.py
Executable file
117
scripts/create-release.py
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Create a Gitea release and upload a .deb package as an asset.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 create-release.py --tag v1.0.0 --deb linux-patch-manager_1.0.0-1_amd64.deb
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
GITEA_TOKEN - API token (required, falls back to GITHUB_TOKEN)
|
||||||
|
GITEA_URL - Gitea base URL (default: http://192.168.2.189:3000)
|
||||||
|
GITEA_REPO - Repository path (default: echo/linux_patch_manager)
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import urllib.request
|
||||||
|
import urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
def create_release(base_url, repo, token, tag, title, body):
|
||||||
|
url = f"{base_url}/api/v1/repos/{repo}/releases"
|
||||||
|
data = json.dumps({
|
||||||
|
"tag_name": tag,
|
||||||
|
"title": title,
|
||||||
|
"body": body,
|
||||||
|
}).encode()
|
||||||
|
req = urllib.request.Request(
|
||||||
|
url,
|
||||||
|
data=data,
|
||||||
|
headers={
|
||||||
|
"Authorization": f"token {token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method="POST",
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
resp = urllib.request.urlopen(req)
|
||||||
|
result = json.loads(resp.read())
|
||||||
|
return result
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
print(f"ERROR: Failed to create release (HTTP {e.code}): {e.read().decode()[:500]}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def upload_asset(base_url, repo, token, release_id, deb_path):
|
||||||
|
url = f"{base_url}/api/v1/repos/{repo}/releases/{release_id}/assets"
|
||||||
|
filename = os.path.basename(deb_path)
|
||||||
|
boundary = "----FormBoundary7MA4YWxkTrZu0gW"
|
||||||
|
with open(deb_path, "rb") as f:
|
||||||
|
deb_data = f.read()
|
||||||
|
body = (
|
||||||
|
f"--{boundary}\r\n"
|
||||||
|
f'Content-Disposition: form-data; name="attachment"; filename="{filename}"\r\n'
|
||||||
|
f"Content-Type: application/octet-stream\r\n\r\n"
|
||||||
|
).encode() + deb_data + (
|
||||||
|
f"\r\n--{boundary}\r\n"
|
||||||
|
f'Content-Disposition: form-data; name="name"\r\n\r\n'
|
||||||
|
f"{filename}\r\n"
|
||||||
|
f"--{boundary}--\r\n"
|
||||||
|
).encode()
|
||||||
|
req = urllib.request.Request(
|
||||||
|
url,
|
||||||
|
data=body,
|
||||||
|
headers={
|
||||||
|
"Authorization": f"token {token}",
|
||||||
|
"Content-Type": f"multipart/form-data; boundary={boundary}",
|
||||||
|
},
|
||||||
|
method="POST",
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
resp = urllib.request.urlopen(req)
|
||||||
|
result = json.loads(resp.read())
|
||||||
|
return result
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
print(f"ERROR: Failed to upload asset (HTTP {e.code}): {e.read().decode()[:500]}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Create Gitea release with .deb asset")
|
||||||
|
parser.add_argument("--tag", required=True, help="Tag name (e.g. v1.0.0)")
|
||||||
|
parser.add_argument("--deb", required=True, help="Path to .deb file")
|
||||||
|
parser.add_argument("--version", required=True, help="Version string")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
token = os.environ.get("GITEA_TOKEN", os.environ.get("GITHUB_TOKEN", ""))
|
||||||
|
if not token:
|
||||||
|
print("ERROR: GITEA_TOKEN or GITHUB_TOKEN not set")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
base_url = os.environ.get("GITEA_URL", "http://192.168.2.189:3000")
|
||||||
|
repo = os.environ.get("GITEA_REPO", "echo/linux_patch_manager")
|
||||||
|
|
||||||
|
title = f"Release {args.version}"
|
||||||
|
body = (
|
||||||
|
f"Automated build from tag {args.tag}.\n\n"
|
||||||
|
f"## Installation\n\n"
|
||||||
|
f"```bash\n"
|
||||||
|
f"sudo apt install ./{os.path.basename(args.deb)}\n"
|
||||||
|
f"```\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Creating release for tag: {args.tag} repo: {repo}")
|
||||||
|
print(f"DEB: {args.deb}")
|
||||||
|
|
||||||
|
release = create_release(base_url, repo, token, args.tag, title, body)
|
||||||
|
release_id = release["id"]
|
||||||
|
print(f"Release created! ID: {release_id}")
|
||||||
|
|
||||||
|
asset = upload_asset(base_url, repo, token, release_id, args.deb)
|
||||||
|
print(f"Upload SUCCESS! Asset ID: {asset.get('id')}")
|
||||||
|
print(f"Download URL: {asset.get('browser_download_url', 'N/A')}")
|
||||||
|
print("Release upload complete")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user