Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ jobs:
if: always()
run: docker compose down -v -t 60

kind-up:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v7
- uses: azure/setup-helm@v4
with:
version: v3.19.0
- uses: helm/kind-action@v1.15.2
with:
version: v0.31.0
cluster_name: pyxis-check
- name: On kind, the chart with a synthetic tuner, the bundled database and no GPU comes up, app and vela answer, and app subscribes to the driver
run: scripts/check-kind.sh
env:
PYXIS_KIND_KEEP: 1

chart:
runs-on: ubuntu-latest
env:
Expand Down
101 changes: 101 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Release

on:
push:
tags: ['v*']

env:
HELM_VERSION: v3.19.0
CHART_REGISTRY: oci://ghcr.io/newworldorg/charts

jobs:
version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
prerelease: ${{ steps.version.outputs.prerelease }}
previous: ${{ steps.version.outputs.previous }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: azure/setup-helm@v4
with:
version: ${{ env.HELM_VERSION }}
- name: The tag names the version Chart.yaml declares, and appVersion is the same number
id: version
run: |
version=$(sed -n 's/^version: *//p' charts/pyxis/Chart.yaml)
app_version=$(sed -n 's/^appVersion: *//p' charts/pyxis/Chart.yaml)
if [ "${GITHUB_REF_NAME}" != "v${version}" ]; then
echo "the tag ${GITHUB_REF_NAME} is not v${version}, the version Chart.yaml declares" >&2
exit 1
fi
if [ "${app_version}" != "${version}" ]; then
echo "appVersion ${app_version} is not the chart version ${version}" >&2
exit 1
fi
case "${version}" in
*-*) prerelease=yes ;;
*) prerelease=no ;;
esac
previous=$(git tag --list 'v*' --sort=-v:refname | grep -vx "${GITHUB_REF_NAME}" | head -n 1 || true)
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "prerelease=${prerelease}" >> "${GITHUB_OUTPUT}"
echo "previous=${previous}" >> "${GITHUB_OUTPUT}"
- name: The images in compose.yml, values.yaml and Chart.yaml are the same versions
run: scripts/check-versions.sh
- name: No chart of this version is in the registry yet
run: |
if helm show chart "${CHART_REGISTRY}/pyxis" --version "${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
echo "pyxis ${{ steps.version.outputs.version }} is already in ${CHART_REGISTRY}" >&2
exit 1
fi

chart:
needs: version
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v7
- uses: azure/setup-helm@v4
with:
version: ${{ env.HELM_VERSION }}
- name: helm lint with every set of values under ci/
run: |
for values in charts/pyxis/ci/*-values.yaml; do
helm lint --strict charts/pyxis -f "${values}"
done
- name: Package and push the chart to the registry
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io --username "${{ github.actor }}" --password-stdin
helm package charts/pyxis --destination "${RUNNER_TEMP}"
helm push "${RUNNER_TEMP}/pyxis-${{ needs.version.outputs.version }}.tgz" "${CHART_REGISTRY}"
- name: The pushed chart can be read back by version
run: helm show chart "${CHART_REGISTRY}/pyxis" --version "${{ needs.version.outputs.version }}"

github-release:
needs: [version, chart]
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: A GitHub Release for the tag, with the images this version pins and whether the driver changes
run: |
if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
echo "the release ${GITHUB_REF_NAME} is already there and is left as it is."
exit 0
fi
scripts/release-notes.sh "${{ needs.version.outputs.previous }}" > "${RUNNER_TEMP}/notes.md"
flags=""
if [ "${{ needs.version.outputs.prerelease }}" = yes ]; then
flags="--prerelease"
fi
gh release create "${GITHUB_REF_NAME}" --verify-tag --title "${GITHUB_REF_NAME}" --notes-file "${RUNNER_TEMP}/notes.md" ${flags}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ docker compose logs driver

イメージの版は `compose.yml` と `charts/pyxis/values.yaml` に数字で書いてあり、`latest` は使わない。\
2 か所が同じ版であることは CI が確かめる。\
PR のたびに compose は Docker で、チャートは kind で起動し、画面と API が答えることも CI が見る。\
Pyxis の版は、その組で起動・録画・再生を確かめてから付ける。

## ライセンス
Expand Down
14 changes: 14 additions & 0 deletions charts/pyxis/ci/kind-sizes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# kind での起動の試験で default-values.yaml に重ねる値。名前を *-values.yaml にしないのは、chart の job が単体で lint と描画をする組と区別するため。置き場を小さくし、そのほかは既定のまま
persistence:
recordings:
size: 1Gi
encodes:
size: 1Gi
thumbnails:
size: 256Mi
captions:
size: 256Mi
keys:
size: 64Mi
db:
size: 1Gi
89 changes: 89 additions & 0 deletions scripts/check-kind.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
# 今の kubectl の context (kind) に、既定の値と ci/kind-sizes.yaml でチャートを入れ、
# app の /api/health と vela の /login が 200 を返し、app が driver の口 (/events) につないだことを確かめる。
# 終わったらリリースと名前空間を消す
set -euo pipefail

cd "$(dirname "$0")/.."

namespace=${PYXIS_KIND_NAMESPACE:-pyxis-check}
release=carina
app_port=${PYXIS_KIND_APP_PORT:-18080}
vela_port=${PYXIS_KIND_VELA_PORT:-13000}
forwards=()

cleanup() {
for pid in "${forwards[@]}"; do
kill "$pid" 2>/dev/null || true
done
if [ "${PYXIS_KIND_KEEP:-}" != 1 ]; then
helm uninstall "$release" -n "$namespace" --wait --timeout 5m >/dev/null 2>&1 || true
kubectl delete namespace "$namespace" --wait=false >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT

describe_failure() {
echo '== pods'
kubectl -n "$namespace" get pods -o wide
echo '== events'
kubectl -n "$namespace" get events --sort-by=.lastTimestamp | tail -n 40
for part in driver app vela db; do
echo "== logs ${release}-${part}"
kubectl -n "$namespace" logs "deploy/${release}-${part}" --all-containers --tail=60 2>/dev/null \
|| kubectl -n "$namespace" logs "statefulset/${release}-${part}" --all-containers --tail=60 2>/dev/null \
|| true
done
}

kubectl create namespace "$namespace" --dry-run=client -o yaml | kubectl apply -f - >/dev/null
# driver は privileged で動く
kubectl label namespace "$namespace" pod-security.kubernetes.io/enforce=privileged --overwrite >/dev/null

if ! helm upgrade --install "$release" charts/pyxis -n "$namespace" \
-f charts/pyxis/ci/default-values.yaml -f charts/pyxis/ci/kind-sizes.yaml \
--wait --timeout 10m; then
describe_failure
exit 1
fi

kubectl -n "$namespace" port-forward "svc/${release}-app" "${app_port}:8080" >/dev/null 2>&1 &
forwards+=("$!")
kubectl -n "$namespace" port-forward "svc/${release}-vela" "${vela_port}:3000" >/dev/null 2>&1 &
forwards+=("$!")

health=''
login=''
for _ in $(seq 1 60); do
health=$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${app_port}/api/health" || true)
login=$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${vela_port}/login" || true)
if [ "$health" = 200 ] && [ "$login" = 200 ]; then
break
fi
sleep 1
done
echo "health=${health} login=${login}"
if [ "$health" != 200 ] || [ "$login" != 200 ]; then
describe_failure
exit 1
fi
curl -s "http://127.0.0.1:${app_port}/api/health"
echo

# app は driver の口につなぐと、まず /events を購読する。driver の要求のログにそれが残る
subscribed=''
for _ in $(seq 1 60); do
if kubectl -n "$namespace" logs "deploy/${release}-driver" --tail=-1 | grep -q 'GET http://driver/events'; then
subscribed=yes
break
fi
sleep 1
done
if [ -z "$subscribed" ]; then
echo 'app が driver の /events を購読した記録が driver のログに無い' >&2
describe_failure
exit 1
fi
echo 'app が driver の /events を購読した'

kubectl -n "$namespace" get pods -o custom-columns='NAME:.metadata.name,READY:.status.containerStatuses[*].ready,PHASE:.status.phase' --no-headers
51 changes: 51 additions & 0 deletions scripts/release-notes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# GitHub Release の本文を書く。この版が固定するイメージの表と、前の版から driver が替わるかどうか。
# 引数は前の版のタグ (無ければ空)
set -euo pipefail

cd "$(dirname "$0")/.."

previous=${1:-}

image_of() {
local ref=$1
local part=$2
if [ -z "$ref" ]; then
return 0
fi
local image
image=$(git show "${ref}:charts/pyxis/Chart.yaml" | sed -n "s/^ *images\/${part}: *//p")
# v0.1.0 より前の Chart.yaml は driver を images/carina-driver と書いていた
if [ -z "$image" ] && [ "$part" = puppis-driver ]; then
image=$(git show "${ref}:charts/pyxis/Chart.yaml" | sed -n 's/^ *images\/carina-driver: *//p')
fi
printf '%s' "$image"
}

row() {
local label=$1
local part=$2
local image
image=$(sed -n "s/^ *images\/${part}: *//p" charts/pyxis/Chart.yaml)
printf '| %s | `%s` |\n' "$label" "$image"
}

echo '| 部品 | イメージ |'
echo '| --- | --- |'
row 'Carina' carina-app
row 'Puppis (driver)' puppis-driver
row 'Vela' vela
row 'PostgreSQL' postgres
echo

driver_now=$(image_of HEAD puppis-driver)
driver_before=$(image_of "$previous" puppis-driver)
if [ -z "$previous" ]; then
echo '最初の版。'
elif [ "$driver_now" = "$driver_before" ]; then
echo "driver のイメージは ${previous} と同じ。更新しても driver は作り直されず、録画は続く。"
else
echo "driver のイメージが ${previous} の \`${driver_before}\` から替わる。録画中とライブの視聴中を避けて更新する。"
fi
echo
echo "compose は \`git checkout ${GITHUB_REF_NAME:-$(git describe --tags --exact-match 2>/dev/null || echo HEAD)}\` して \`docker compose pull\` と \`docker compose up -d\`、Helm は \`helm upgrade carina oci://ghcr.io/newworldorg/charts/pyxis --version $(sed -n 's/^version: *//p' charts/pyxis/Chart.yaml) -n tv -f values.yaml\`。"
Loading