minor: add a new release system #3
3
.gitignore
vendored
3
.gitignore
vendored
@@ -44,3 +44,6 @@ data
|
|||||||
|
|
||||||
# Dev TLS certs (self-signed for local testing)
|
# Dev TLS certs (self-signed for local testing)
|
||||||
.dev-certs
|
.dev-certs
|
||||||
|
|
||||||
|
# CI artifact (kaniko reads .tags for image tag list)
|
||||||
|
.tags
|
||||||
|
|||||||
@@ -3,14 +3,34 @@ when:
|
|||||||
branch: main
|
branch: main
|
||||||
|
|
||||||
steps:
|
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
|
image: woodpeckerci/plugin-kaniko
|
||||||
|
depends_on: [release]
|
||||||
settings:
|
settings:
|
||||||
repo: ${CI_REPO_OWNER}/${CI_REPO_NAME}
|
repo: ${CI_REPO_OWNER}/${CI_REPO_NAME}
|
||||||
registry: git.keligrubb.com
|
registry: git.keligrubb.com
|
||||||
tags: latest,${CI_COMMIT_SHA:0:7}
|
|
||||||
username: ${CI_REPO_OWNER}
|
username: ${CI_REPO_OWNER}
|
||||||
password:
|
password:
|
||||||
from_secret: gitea_registry_token
|
from_secret: gitea_registry_token
|
||||||
single-snapshot: true
|
single-snapshot: true
|
||||||
cleanup: 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
3
CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
20
README.md
20
README.md
@@ -77,12 +77,30 @@ docker run -p 3000:3000 kestrelos:latest
|
|||||||
|
|
||||||
## Kubernetes (Helm)
|
## Kubernetes (Helm)
|
||||||
|
|
||||||
|
**From Gitea registry:**
|
||||||
```bash
|
```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`.
|
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
|
## Security
|
||||||
|
|
||||||
- Device data is validated server-side; only valid entries are returned.
|
- Device data is validated server-side; only valid entries are returned.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
replicaCount: 1
|
replicaCount: 1
|
||||||
|
|
||||||
image:
|
image:
|
||||||
repository: kestrelos
|
repository: git.keligrubb.com/keligrubb/kestrelos
|
||||||
tag: latest
|
tag: latest
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
|||||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -22,6 +22,7 @@
|
|||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@iconify-json/tabler": "^1.2.26",
|
||||||
"@nuxt/eslint": "^1.15.0",
|
"@nuxt/eslint": "^1.15.0",
|
||||||
"@nuxt/test-utils": "^4.0.0",
|
"@nuxt/test-utils": "^4.0.0",
|
||||||
"@playwright/test": "^1.58.2",
|
"@playwright/test": "^1.58.2",
|
||||||
@@ -1433,6 +1434,16 @@
|
|||||||
"url": "https://github.com/sponsors/nzakas"
|
"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": {
|
"node_modules/@iconify/collections": {
|
||||||
"version": "1.0.649",
|
"version": "1.0.649",
|
||||||
"resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.649.tgz",
|
"resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.649.tgz",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kestrelos",
|
"name": "kestrelos",
|
||||||
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@iconify-json/tabler": "^1.2.26",
|
||||||
"@nuxt/eslint": "^1.15.0",
|
"@nuxt/eslint": "^1.15.0",
|
||||||
"@nuxt/test-utils": "^4.0.0",
|
"@nuxt/test-utils": "^4.0.0",
|
||||||
"@playwright/test": "^1.58.2",
|
"@playwright/test": "^1.58.2",
|
||||||
|
|||||||
56
scripts/release.sh
Executable file
56
scripts/release.sh
Executable 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"
|
||||||
Reference in New Issue
Block a user