add a new release system
All checks were successful
ci/woodpecker/pr/pr Pipeline was successful

This commit is contained in:
Madison Grubb
2026-02-12 16:58:48 -05:00
parent 547b94bac8
commit 03ee661275
8 changed files with 117 additions and 4 deletions

3
.gitignore vendored
View File

@@ -44,3 +44,6 @@ data
# Dev TLS certs (self-signed for local testing)
.dev-certs
# CI artifact (kaniko reads .tags for image tag list)
.tags

View File

@@ -3,14 +3,34 @@ when:
branch: main
steps:
- name: docker-build-push
- name: release
image: alpine
commands:
- apk add --no-cache git
- ./scripts/release.sh
environment:
GITEA_REPO_TOKEN:
from_secret: gitea_repo_token
- name: docker
image: woodpeckerci/plugin-kaniko
depends_on: [release]
settings:
repo: ${CI_REPO_OWNER}/${CI_REPO_NAME}
registry: git.keligrubb.com
tags: latest,${CI_COMMIT_SHA:0:7}
username: ${CI_REPO_OWNER}
password:
from_secret: gitea_registry_token
single-snapshot: true
cleanup: true
- name: helm
image: alpine/helm
depends_on: [release]
environment:
GITEA_REGISTRY_TOKEN:
from_secret: gitea_registry_token
commands:
- apk add --no-cache curl
- helm package helm/kestrelos
- curl -sf -u $CI_REPO_OWNER:$GITEA_REGISTRY_TOKEN -X POST --upload-file kestrelos-*.tgz https://git.keligrubb.com/api/packages/$CI_REPO_OWNER/helm/api/charts

3
CHANGELOG.md Normal file
View File

@@ -0,0 +1,3 @@
# Changelog
All notable changes to this project will be documented in this file.

View File

@@ -77,12 +77,30 @@ docker run -p 3000:3000 kestrelos:latest
## Kubernetes (Helm)
**From Gitea registry:**
```bash
helm install kestrelos ./helm/kestrelos --set image.repository=your-registry/kestrelos --set image.tag=latest
helm repo add keligrubb --username YOUR_USER --password YOUR_TOKEN https://git.keligrubb.com/api/packages/keligrubb/helm
helm repo update
helm install kestrelos keligrubb/kestrelos
```
**From source:**
```bash
helm install kestrelos ./helm/kestrelos
```
Health: `GET /health` (overview), `GET /health/live` (liveness), `GET /health/ready` (readiness). Probes are configured in the Helm chart. Optional: enable Ingress in `helm/kestrelos/values.yaml`.
## Releases
Merges to `main` trigger a semver release. Use one of these prefixes in your PR title to set the version bump:
- `major:` breaking changes
- `minor:` new features
- `patch:` bug fixes, docs (default if no prefix)
Example: `minor: Add map layer toggle`
## Security
- Device data is validated server-side; only valid entries are returned.

View File

@@ -1,7 +1,7 @@
replicaCount: 1
image:
repository: kestrelos
repository: git.keligrubb.com/keligrubb/kestrelos
tag: latest
pullPolicy: IfNotPresent

11
package-lock.json generated
View File

@@ -22,6 +22,7 @@
"ws": "^8.18.0"
},
"devDependencies": {
"@iconify-json/tabler": "^1.2.26",
"@nuxt/eslint": "^1.15.0",
"@nuxt/test-utils": "^4.0.0",
"@playwright/test": "^1.58.2",
@@ -1433,6 +1434,16 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@iconify-json/tabler": {
"version": "1.2.26",
"resolved": "https://registry.npmjs.org/@iconify-json/tabler/-/tabler-1.2.26.tgz",
"integrity": "sha512-92G+ZD70AZgeJf07JfQzH+isnai6DwPcMBuF/qL1F+xAxdXCJzGd3w2RmsRvOmB+w1ImmWEEDms50QivQIjd6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@iconify/types": "*"
}
},
"node_modules/@iconify/collections": {
"version": "1.0.649",
"resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.649.tgz",

View File

@@ -1,5 +1,6 @@
{
"name": "kestrelos",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
@@ -32,6 +33,7 @@
"ws": "^8.18.0"
},
"devDependencies": {
"@iconify-json/tabler": "^1.2.26",
"@nuxt/eslint": "^1.15.0",
"@nuxt/test-utils": "^4.0.0",
"@playwright/test": "^1.58.2",

56
scripts/release.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/sh
set -e
# version
msg="${CI_COMMIT_MESSAGE:-}"
bump=patch
echo "$msg" | grep -qi minor: && bump=minor
echo "$msg" | grep -qi major: && bump=major
cur=$(awk '/"version"/ { match($0, /[0-9]+\.[0-9]+\.[0-9]+/); print substr($0, RSTART, RLENGTH); exit }' package.json)
major=$(echo "$cur" | cut -d. -f1); minor=$(echo "$cur" | cut -d. -f2); patch=$(echo "$cur" | cut -d. -f3)
case "$bump" in major) major=$((major+1)); minor=0; patch=0 ;; minor) minor=$((minor+1)); patch=0 ;; patch) patch=$((patch+1)) ;; esac
newVersion="$major.$minor.$patch"
[ -z "$cur" ] && { echo "error: could not read version from package.json"; exit 1; }
# changelog entry (strip prefix from first line)
changelogEntry=$(echo "$msg" | head -1 | awk '{sub(/^[mM]ajor:[ \t]*/,""); sub(/^[mM]inor:[ \t]*/,""); sub(/^[pP]atch:[ \t]*/,""); print}')
[ -z "$changelogEntry" ] && changelogEntry="Release v$newVersion"
# bump files
awk -v v="$newVersion" '/"version"/ { sub(/[0-9]+\.[0-9]+\.[0-9]+/, v) } { print }' package.json > package.json.tmp && mv package.json.tmp package.json
awk -v v="$newVersion" '/^version:/ { $0 = "version: " v }; /^appVersion:/ { $0 = "appVersion: \"" v "\"" }; { print }' helm/kestrelos/Chart.yaml > helm/kestrelos/Chart.yaml.tmp && mv helm/kestrelos/Chart.yaml.tmp helm/kestrelos/Chart.yaml
awk -v v="$newVersion" '/^ tag:/ { $0 = " tag: " v }; { print }' helm/kestrelos/values.yaml > helm/kestrelos/values.yaml.tmp && mv helm/kestrelos/values.yaml.tmp helm/kestrelos/values.yaml
# changelog
new="## [$newVersion] - $(date +%Y-%m-%d)
### Changed
- $changelogEntry
"
{ [ ! -f CHANGELOG.md ] && printf '# Changelog\n\n'; printf '%s' "$new"; [ -f CHANGELOG.md ] && cat CHANGELOG.md; } > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md
# git
git config user.email "ci@kestrelos" && git config user.name "CI"
git add package.json helm/kestrelos/Chart.yaml helm/kestrelos/values.yaml CHANGELOG.md
git commit -m "release v$newVersion [skip ci]"
url="https://${CI_REPO_OWNER}:${GITEA_REPO_TOKEN}@${CI_FORGE_URL#https://}/${CI_REPO_OWNER}/${CI_REPO_NAME}.git"
git tag "v$newVersion"
# artifact for kaniko (tag list)
printf '%s\n%s\n' "$newVersion" "latest" > .tags
retry() { n=0; while ! "$@"; do n=$((n+1)); [ $n -ge 3 ] && return 1; sleep 2; done; }
retry git push "$url" HEAD:main "v$newVersion"
# gitea release
body="## Changelog
### Changed
- $changelogEntry
## Installation
- [Docker image](${CI_FORGE_URL}/${CI_REPO_OWNER}/-/packages/container/${CI_REPO_NAME})
- [Helm chart](${CI_FORGE_URL}/${CI_REPO_OWNER}/-/packages/helm)"
release_url="${CI_FORGE_URL}/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases"
echo "$body" | awk -v tag="v$newVersion" 'BEGIN{printf "{\"tag_name\":\"" tag "\",\"name\":\"" tag "\",\"body\":\""} { gsub(/\\/,"\\\\"); gsub(/"/,"\\\""); if (NR>1) printf "\\n"; printf "%s", $0 } END{printf "\"}\n"}' > /tmp/release.json
wget -q -O /dev/null --post-file=/tmp/release.json \
--header="Authorization: token ${GITEA_REPO_TOKEN}" \
--header="Content-Type: application/json" \
"$release_url"