Compare commits
10
Commits
78b9b59eca
..
v0.6.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f50dd6be6a | ||
|
|
1906a774b3 | ||
|
|
38f905e705 | ||
|
|
7db7e0779b | ||
|
|
0be3506799 | ||
|
|
6151b973bc | ||
|
|
6c1b6ce9db | ||
|
|
5c8341c797 | ||
|
|
5ca44c9c6b | ||
|
|
e2a312d05e |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "skills",
|
"name": "skills",
|
||||||
"description": "Mathias's engineering skills library, plus the hooks and MCP servers that make it enforceable: TDD, clean code, debugging, specs, discovery, CI, and secret hygiene.",
|
"description": "Mathias's engineering skills library, plus the hooks and MCP servers that make it enforceable: TDD, clean code, debugging, specs, discovery, CI, and secret hygiene.",
|
||||||
"version": "0.3.3",
|
"version": "0.6.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Mathias",
|
"name": "Mathias",
|
||||||
"url": "https://git.d-ma.be/mathias"
|
"url": "https://git.d-ma.be/mathias"
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
last_commit=$(git log -1 --pretty=%B)
|
last_commit=$(git log -1 --pretty=%B)
|
||||||
if printf '%s' "$last_commit" | grep -qi '\[skip-release\]'; then
|
# Delegated to bin/should-skip-release so the rule is covered by
|
||||||
echo "skipping — commit marked [skip-release]"
|
# tests/release_skip_test.sh rather than living untested in YAML.
|
||||||
|
if printf '%s\n' "$last_commit" | sh bin/should-skip-release; then
|
||||||
|
echo "skipping — commit carries the Skip-Release trailer"
|
||||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@@ -73,8 +75,8 @@ jobs:
|
|||||||
if [ "$current" != "$version" ]; then
|
if [ "$current" != "$version" ]; then
|
||||||
sed -i "s/\"version\"[[:space:]]*:[[:space:]]*\"$current\"/\"version\": \"$version\"/" "$manifest"
|
sed -i "s/\"version\"[[:space:]]*:[[:space:]]*\"$current\"/\"version\": \"$version\"/" "$manifest"
|
||||||
git add "$manifest"
|
git add "$manifest"
|
||||||
# [skip-release] stops this push from re-triggering the tagger.
|
# The trailer below stops this push from re-triggering the tagger.
|
||||||
git commit -m "chore(release): plugin.json version $version [skip-release]"
|
git commit -m "chore(release): plugin.json version $version" -m "Skip-Release: true"
|
||||||
git push origin HEAD:main
|
git push origin HEAD:main
|
||||||
echo "bumped $manifest to $version"
|
echo "bumped $manifest to $version"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
{
|
{
|
||||||
|
"_comment": "Tailscale Serve on koala, not the public d-ma.be hostnames. The public path exits to Cloudflare and NPM to reach a k3s service on the same machine most sessions run on, which imposes rate limits and message-size caps on tool results. Serve terminates TLS with a real Tailscale cert and proxies to the NodePort over loopback, so traffic reaches the service from koala itself and satisfies the default-deny-ingress NetworkPolicy with no cluster change. Clients need 'tailscale set --accept-dns=true' for the MagicDNS name to resolve; see mathias/skills#24.",
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"brain": {
|
"brain": {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"url": "https://brain-mcp.d-ma.be/mcp",
|
"url": "https://koala.tail30472e.ts.net:8443/mcp",
|
||||||
"headers": {
|
"headers": {
|
||||||
"Authorization": "Bearer ${BRAIN_MCP_TOKEN}"
|
"Authorization": "Bearer ${BRAIN_MCP_TOKEN}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gitea": {
|
|
||||||
"type": "http",
|
|
||||||
"url": "https://git-mcp.d-ma.be/mcp",
|
|
||||||
"headers": {
|
|
||||||
"Authorization": "Bearer ${GITEA_MCP_TOKEN}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"infra": {
|
"infra": {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"url": "https://infra-mcp.d-ma.be/mcp"
|
"url": "https://koala.tail30472e.ts.net:8444/mcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Executable
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# should-skip-release — reads a commit message on stdin. Exits 0 when the
|
||||||
|
# release tagger should skip this commit, 1 when it should tag.
|
||||||
|
#
|
||||||
|
# Skipping is opt-in via a git trailer:
|
||||||
|
#
|
||||||
|
# Skip-Release: true
|
||||||
|
#
|
||||||
|
# It is a TRAILER, matched anchored to its own line, deliberately. The first
|
||||||
|
# version searched the whole message for a bracketed marker as a substring,
|
||||||
|
# and the very commit that introduced the manifest-bump step described that
|
||||||
|
# marker in its body — so the tagger read its own documentation as an
|
||||||
|
# instruction and skipped the release. Success, no tag, no bump, no error
|
||||||
|
# (run 15, 2026-08-23). A marker you cannot mention without triggering is a
|
||||||
|
# footgun, not a mechanism.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
msg=$(cat)
|
||||||
|
|
||||||
|
if printf '%s\n' "$msg" | grep -qiE '^[[:space:]]*Skip-Release:[[:space:]]*true[[:space:]]*$'; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 1
|
||||||
+41
-25
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: gitea-ci
|
name: gitea-ci
|
||||||
description: End-to-end Gitea CI/CD setup with self-hosted act_runner, quality gate pipeline, buildah image build, k3s deploy, and GitHub mirror. Covers act_runner-specific gotchas that are not documented anywhere.
|
description: End-to-end Gitea CI/CD setup with self-hosted act_runner, quality gate pipeline, buildctl image build, k3s deploy, and GitHub mirror. Covers act_runner-specific gotchas that are not documented anywhere.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Gitea CI/CD Pipeline Setup
|
# Gitea CI/CD Pipeline Setup
|
||||||
@@ -31,7 +31,7 @@ Before writing any YAML, collect the following. Use AskUserQuestion for anything
|
|||||||
| Container registry | Ask or check existing config | `localhost:5000` on koala, or external |
|
| Container registry | Ask or check existing config | `localhost:5000` on koala, or external |
|
||||||
| k3s namespace | k8s/ manifests or ask | Deploy target |
|
| k3s namespace | k8s/ manifests or ask | Deploy target |
|
||||||
| GitHub mirror repo | Ask | Target for the mirror job |
|
| GitHub mirror repo | Ask | Target for the mirror job |
|
||||||
| Image name | Ask or derive from repo name | Used in buildah + k3s steps |
|
| Image name | Ask or derive from repo name | Used in buildctl + k3s steps |
|
||||||
|
|
||||||
Check the project's `CLAUDE.md` for infra notes first — often this answers most questions without needing to ask.
|
Check the project's `CLAUDE.md` for infra notes first — often this answers most questions without needing to ask.
|
||||||
|
|
||||||
@@ -135,33 +135,49 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push to local registry
|
- name: Build and push to local registry
|
||||||
run: |
|
run: |
|
||||||
|
set -e
|
||||||
|
# buildctl, NOT buildah (infra#241). The runner is a pod with
|
||||||
|
# `capabilities: drop [ALL]` and `allowPrivilegeEscalation: false`,
|
||||||
|
# so rootless buildah cannot remap UID/GID for a fresh base-image
|
||||||
|
# pull and the pod has no OCI runtime -- every `RUN` step fails.
|
||||||
|
# buildctl is a thin client: it hands the build to the host's
|
||||||
|
# buildkitd over a socket, so the privileged work happens on the
|
||||||
|
# host and the pod's securityContext is not in the picture.
|
||||||
|
# The failure is LATENT -- warm base-image layers mask it, so a
|
||||||
|
# buildah step can look fine for weeks and then fail on a cold pull.
|
||||||
|
BUILDKIT_HOST="unix:///run/buildkit/buildkitd.sock"
|
||||||
REGISTRY="localhost:5000"
|
REGISTRY="localhost:5000"
|
||||||
REF="${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.sha-tag }}"
|
REF="${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.sha-tag }}"
|
||||||
buildah build \
|
TAR_FILE="$(mktemp)"
|
||||||
--label "org.opencontainers.image.revision=${{ github.sha }}" \
|
trap 'rm -f "$TAR_FILE"' EXIT
|
||||||
--label "org.opencontainers.image.source=${{ github.repositoryUrl }}" \
|
|
||||||
-t ${REF} \
|
buildctl --addr "$BUILDKIT_HOST" build \
|
||||||
-t ${REGISTRY}/${{ env.IMAGE }}:latest \
|
--frontend dockerfile.v0 \
|
||||||
.
|
--local context=. \
|
||||||
buildah push --tls-verify=false ${REF}
|
--local dockerfile=. \
|
||||||
buildah push --tls-verify=false ${REGISTRY}/${{ env.IMAGE }}:latest
|
--opt label:org.opencontainers.image.revision="${{ github.sha }}" \
|
||||||
[[ -n "${{ steps.meta.outputs.version-tag }}" ]] && \
|
--opt label:org.opencontainers.image.source="${{ github.repositoryUrl }}" \
|
||||||
buildah push --tls-verify=false \
|
--output type=oci,dest="$TAR_FILE"
|
||||||
${REF} \
|
|
||||||
${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.version-tag }} || true
|
# buildctl has no registry-push equivalent to `buildah push`; skopeo
|
||||||
|
# copies the OCI archive up, once per tag.
|
||||||
|
skopeo copy --dest-tls-verify=false \
|
||||||
|
oci-archive:"$TAR_FILE" docker://${REF}
|
||||||
|
skopeo copy --dest-tls-verify=false \
|
||||||
|
oci-archive:"$TAR_FILE" docker://${REGISTRY}/${{ env.IMAGE }}:latest
|
||||||
|
if [ -n "${{ steps.meta.outputs.version-tag }}" ]; then
|
||||||
|
skopeo copy --dest-tls-verify=false \
|
||||||
|
oci-archive:"$TAR_FILE" \
|
||||||
|
docker://${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.version-tag }}
|
||||||
|
fi
|
||||||
echo "✓ Image pushed to ${REF}"
|
echo "✓ Image pushed to ${REF}"
|
||||||
|
|
||||||
- name: Smoke test
|
# No smoke test step. The one this skill used to recommend ran
|
||||||
run: |
|
# `sudo k3s ctr run` against the host's containerd -- that worked when
|
||||||
REGISTRY="localhost:5000"
|
# the runner was the Arch host, and is impossible now that it is a pod:
|
||||||
REF="${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.sha-tag }}"
|
# no sudo, no ctr, no containerd socket (`sudo: command not found`).
|
||||||
CNAME="smoke-${{ steps.meta.outputs.sha-tag }}"
|
# The deploy job's `Verify rollout` + `Confirm pod running new image`
|
||||||
sudo k3s ctr images pull --plain-http ${REF}
|
# below assert the same property against the real workload.
|
||||||
OUTPUT=$(timeout 5 sudo k3s ctr run --rm ${REF} ${CNAME} /<binary-name> 2>&1 || true)
|
|
||||||
sudo k3s ctr containers delete ${CNAME} 2>/dev/null || true
|
|
||||||
echo "$OUTPUT" | grep -q "<project-name>" \
|
|
||||||
&& echo "✓ Smoke test passed" \
|
|
||||||
|| echo "⚠ Smoke test inconclusive: $OUTPUT"
|
|
||||||
|
|
||||||
# ── 3. Deploy to k3s ────────────────────────────────────────────────────────
|
# ── 3. Deploy to k3s ────────────────────────────────────────────────────────
|
||||||
deploy:
|
deploy:
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Tests for bin/should-skip-release.
|
||||||
|
#
|
||||||
|
# The regression these exist for: an unanchored substring match let a commit
|
||||||
|
# that merely *described* the skip marker skip its own release.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
||||||
|
SUT="$ROOT/bin/should-skip-release"
|
||||||
|
|
||||||
|
pass=0
|
||||||
|
fail=0
|
||||||
|
|
||||||
|
if [ ! -f "$SUT" ]; then
|
||||||
|
printf 'FAIL: %s does not exist\n' "$SUT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# expect <skip|tag> <label> <<message on stdin>>
|
||||||
|
expect() {
|
||||||
|
_want=$1
|
||||||
|
_label=$2
|
||||||
|
_msg=$3
|
||||||
|
printf '%s\n' "$_msg" | sh "$SUT"
|
||||||
|
_rc=$?
|
||||||
|
if [ "$_want" = skip ]; then _wrc=0; else _wrc=1; fi
|
||||||
|
if [ "$_rc" -eq "$_wrc" ]; then
|
||||||
|
pass=$((pass + 1)); printf ' ok %s\n' "$_label"
|
||||||
|
else
|
||||||
|
fail=$((fail + 1)); printf ' FAIL %s (want %s, rc=%s)\n' "$_label" "$_want" "$_rc"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
expect skip 'trailer on its own line' 'chore(release): bump
|
||||||
|
|
||||||
|
Skip-Release: true'
|
||||||
|
|
||||||
|
expect skip 'trailer, case-insensitive' 'chore: x
|
||||||
|
|
||||||
|
skip-release: TRUE'
|
||||||
|
|
||||||
|
expect tag 'ordinary commit' 'feat: add a thing
|
||||||
|
|
||||||
|
Bump-Type: minor'
|
||||||
|
|
||||||
|
# --- the actual regression -------------------------------------------------
|
||||||
|
expect tag 'prose MENTIONING the marker must still tag' 'docs+ci: document the release flow
|
||||||
|
|
||||||
|
CI commits the manifest bump with a Skip-Release: true trailer so it does
|
||||||
|
not re-trigger the tagger. The old [skip-release] marker was a substring
|
||||||
|
match, which is exactly why this commit would have skipped itself.
|
||||||
|
|
||||||
|
Bump-Type: patch'
|
||||||
|
|
||||||
|
expect tag 'legacy bracketed marker no longer skips' 'chore: something [skip-release]'
|
||||||
|
|
||||||
|
expect tag 'empty message' ''
|
||||||
|
|
||||||
|
printf '\nrelease_skip: %d passed, %d failed\n' "$pass" "$fail"
|
||||||
|
[ "$fail" -eq 0 ]
|
||||||
Reference in New Issue
Block a user