Hello world
Release / Build and publish (push) Successful in 35s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kebandClaude Opus 5.5 committed 2026-10-12 14:57:17 +02:00
commit f64ec47d71
134 files changed
+27239

No files matched your search

+75
View File
@@ -0,0 +1,75 @@
// Copies a release GoReleaser published on Gitea to the GitHub mirror:
// the same notes and the same files (dist/), so lazysecrets can update
// from either (internal/update tries GitHub first). Run by the release
// workflow after GoReleaser; a release already on GitHub for the tag is
// replaced, like GoReleaser's mode: replace on Gitea.
//
// TAG=v0.2.0 GH_TOKEN=… GITEA_TOKEN=… node scripts/github-release.mjs
//
// GH_TOKEN is a fine-grained token that can write the mirror's contents;
// without it, this does nothing. No dependencies: Node 20's fetch.
import { readdir, readFile } from "node:fs/promises";
const github = "karleinarb/lazysecrets";
const { TAG: tag, GH_TOKEN: token, GITEA_TOKEN: giteaToken, GITHUB_SHA: sha } = process.env;
const gitea = `${process.env.GITHUB_SERVER_URL ?? "https://git.kebcloud.no"}/api/v1/repos/${process.env.GITHUB_REPOSITORY ?? "keb/lazysecrets"}`;
if (!token) {
console.log("No GH_TOKEN: not copying the release to GitHub.");
process.exit(0);
}
if (!tag) throw new Error("TAG isn't set");
const gh = (path, init = {}) =>
fetch(path.startsWith("https://") ? path : `https://api.github.com/repos/${github}${path}`, {
...init,
headers: {
Accept: "application/vnd.github+json",
Authorization: `Bearer ${token}`,
"X-GitHub-Api-Version": "2022-11-28",
...init.headers,
},
});
async function ok(res, what) {
if (!res.ok) throw new Error(`${what}: ${res.status} ${await res.text()}`);
return res;
}
// The notes as GoReleaser wrote them on Gitea.
const rel = await (
await ok(await fetch(`${gitea}/releases/tags/${tag}`, { headers: giteaToken ? { Authorization: `token ${giteaToken}` } : {} }), "reading the Gitea release")
).json();
// Replace what's there for the tag.
const old = await gh(`/releases/tags/${tag}`);
if (old.ok) {
const { id } = await old.json();
await ok(await gh(`/releases/${id}`, { method: "DELETE" }), "deleting the old GitHub release");
console.log(`Deleted the GitHub release for ${tag}.`);
}
// The mirror may not have the tag's commit yet: it pushes on its own.
// Wait for it a while.
const body = JSON.stringify({ tag_name: tag, target_commitish: sha, name: rel.name || tag, body: rel.body, prerelease: rel.prerelease });
let created;
for (let i = 0; ; i++) {
const res = await gh("/releases", { method: "POST", body });
if (res.ok) {
created = await res.json();
break;
}
if (res.status !== 422 || i === 9) await ok(res, "creating the GitHub release");
console.log("GitHub doesn't have the commit yet; waiting for the mirror…");
await new Promise((r) => setTimeout(r, 30_000));
}
const files = (await readdir("dist")).filter((f) => f.endsWith(".tar.gz") || f === "checksums.txt");
if (files.length === 0) throw new Error("nothing to upload in dist/");
for (const f of files) {
const url = `https://uploads.github.com/repos/${github}/releases/${created.id}/assets?name=${encodeURIComponent(f)}`;
await ok(await gh(url, { method: "POST", headers: { "Content-Type": "application/octet-stream" }, body: await readFile(`dist/${f}`) }), `uploading ${f}`);
console.log(`Uploaded ${f}.`);
}
console.log(`Published ${tag} on GitHub: ${created.html_url}`);
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Releases main: writes CHANGELOG.md with git-cliff (cliff.toml), commits
# it, tags the commit and pushes both; the tag runs
# .gitea/workflows/release.yml, which builds and publishes the release.
#
# scripts/release.sh v0.2.0 # or v0.2.0-rc.1 for a pre-release
# scripts/release.sh --dry-run v0.2.0 # print the notes, change nothing
#
# A pre-release is tagged without touching CHANGELOG.md: its changes are
# listed under the release that follows.
set -euo pipefail
dry=false
if [ "${1:-}" = "--dry-run" ]; then
dry=true
shift
fi
tag="${1:?usage: $0 [--dry-run] <tag, e.g. v0.2.0>}"
if ! [[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "$tag is not vMAJOR.MINOR.PATCH (optionally -suffix)" >&2
exit 1
fi
command -v git-cliff >/dev/null || { echo "git-cliff is needed: brew install git-cliff" >&2; exit 1; }
cd "$(dirname "$0")/.."
notes=$(git cliff --unreleased --tag "$tag" --strip all)
if ! grep -q '^- ' <<<"$notes"; then
echo "Nothing for the changelog since the last release (no feat/fix/perf pull requests)." >&2
$dry || exit 1
fi
echo "$notes"
$dry && exit 0
if [ "$(git branch --show-current)" != main ]; then
echo "Release from main." >&2
exit 1
fi
if [ -n "$(git status --porcelain)" ]; then
echo "The working tree has changes; commit or stash them first." >&2
exit 1
fi
git fetch -q origin main --tags
if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/main)" ]; then
echo "main isn't origin/main; pull (or push) first." >&2
exit 1
fi
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
echo "$tag exists already." >&2
exit 1
fi
echo
read -r -p "Release $tag with these notes? [y/N] " ok
[ "$ok" = y ] || [ "$ok" = Y ] || exit 1
if [[ "$tag" != *-* ]]; then
git cliff --tag "$tag" -o CHANGELOG.md
git add CHANGELOG.md
git commit -q -m "chore(release): $tag"
fi
git tag -a "$tag" -m "$tag"
git push -q origin main "$tag"
echo "Pushed $tag: the release workflow builds and publishes it."