2 Commits
Author SHA1 Message Date
sbstp 199d93b3e8 typo in alpine node package
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
2026-07-12 10:42:41 -04:00
sbstp 8bd39e8ce4 fix release pipeline
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/release Pipeline failed
2026-07-12 10:39:04 -04:00
4 changed files with 96 additions and 9 deletions
+1
View File
@@ -1 +1,2 @@
/.build/
/*.sh
+3 -9
View File
@@ -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 nodejs
- node ci/release.js .build/qbittorrent-sentinel
environment:
GITEA_RELEASE_TOKEN:
from_secret: gitea_release_token
+1
View File
@@ -1,2 +1,3 @@
#!/bin/sh
set -eux
CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -o .build/qbittorrent-sentinel
+91
View File
@@ -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 <path>`);
}
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);
}