From 8bd39e8ce4dd5ac9e66e448de4081862bed3a3eb Mon Sep 17 00:00:00 2001 From: Simon Bernier St-Pierre Date: Sun, 12 Jul 2026 10:39:04 -0400 Subject: [PATCH] fix release pipeline --- .gitignore | 1 + .woodpecker/release.yml | 12 ++---- build.sh => ci/build.sh | 1 + ci/release.js | 91 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 9 deletions(-) rename build.sh => ci/build.sh (91%) create mode 100644 ci/release.js diff --git a/.gitignore b/.gitignore index 0e03e15..2917e7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /.build/ +/*.sh diff --git a/.woodpecker/release.yml b/.woodpecker/release.yml index 060c8a4..4f512df 100644 --- a/.woodpecker/release.yml +++ b/.woodpecker/release.yml @@ -6,19 +6,13 @@ steps: image: golang:1.26-alpine3.23 commands: - go mod download - - CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -o qbittorrent-sentinel + - ci/build.sh publish: image: alpine:3.23 commands: - - apk add --no-cache curl - - | - echo "Uploading qbittorrent-sentinel..." - curl -sS -X POST \ - -H "Authorization: token $GITEA_RELEASE_TOKEN" \ - -H "Content-Type: application/octet-stream" \ - --data-binary "@qbittorrent-sentinel" \ - "https://git.sbstp.ca/api/v1/repos/${CI_REPO}/releases/tags/${CI_COMMIT_TAG}/assets?name=qbittorrent-sentinel" + - apk add --no-cache node + - node ci/release.js .build/qbittorrent-sentinel environment: GITEA_RELEASE_TOKEN: from_secret: gitea_release_token diff --git a/build.sh b/ci/build.sh similarity index 91% rename from build.sh rename to ci/build.sh index fb6fb87..500101a 100755 --- a/build.sh +++ b/ci/build.sh @@ -1,2 +1,3 @@ #!/bin/sh +set -eux CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -o .build/qbittorrent-sentinel diff --git a/ci/release.js b/ci/release.js new file mode 100644 index 0000000..9118771 --- /dev/null +++ b/ci/release.js @@ -0,0 +1,91 @@ +import * as fs from 'node:fs/promises'; +import { basename } from 'node:path'; + +function getEnv(name) { + const val = process.env[name]; + if (!val) { + throw new Error(`Environment variable ${name} is empty`); + } + return val; +} + +async function fetchJSON(url, options) { + const resp = await fetch(url, options); + if (!resp.ok) { + throw new Error(`Unexpected HTTP status: ${resp.status}`, { + cause: { + status: resp.status, + body: await resp.text(), + }, + }); + } + return await resp.json(); +} + +async function postJSON(url, token, payload) { + return fetchJSON(url, { + method: "POST", + headers: { + "Authorization": `token ${token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }); +} + +async function postFile(url, token, files) { + const formData = new FormData(); + for (const [name, path] of Object.entries(files)) { + const fileBuffer = await fs.readFile(path); + const fileObject = new File([fileBuffer], basename(path), { type: 'application/octet-stream' }); + formData.append(name, fileObject) + } + return await fetchJSON(url, { + method: "POST", + headers: { + "Authorization": `token ${token}`, + }, + body: formData, + }); +} + +async function canRead(path) { + try { + await fs.access(path, fs.constants.R_OK); + return true; + } catch { + return false; + } +} + +async function main() { + const path = process.argv[2]; + if (!path || !canRead(path)) { + throw Error(`Path ${path} is undefined or inaccessible, use node release.js `); + } + const token = getEnv("GITEA_RELEASE_TOKEN"); + const tag = getEnv("CI_COMMIT_TAG"); + const repo = getEnv("CI_REPO"); + + console.log("Creating release..."); + const releaseData = await postJSON(`https://git.sbstp.ca/api/v1/repos/${repo}/releases`, token, { + name: `Release ${tag}`, + tag_name: tag, + target_commitish: tag, + draft: false, + prerelease: false, + }); + console.log(`Created release ID ${releaseData.id}`); + + console.log("Uploading asset..."); + const assetData = await postFile(`https://git.sbstp.ca/api/v1/repos/${repo}/releases/${releaseData.id}/assets?name=${basename(path)}`, token, { + attachment: path, + }); + console.log("Asset uploaded:", assetData); +} + +try { + await main(); +} catch (err) { + console.error(err); +}