Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4f0416dc5 | ||
|
|
abd81f939a | ||
|
|
e42d2ba9cb | ||
|
|
68cebc0bbb |
@@ -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.6.1",
|
"version": "0.6.3",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Mathias",
|
"name": "Mathias",
|
||||||
"url": "https://git.d-ma.be/mathias"
|
"url": "https://git.d-ma.be/mathias"
|
||||||
|
|||||||
@@ -109,6 +109,15 @@ do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# A real directory where a link belongs holds content nothing manages: it
|
||||||
|
# cannot receive new skills and silently shadows the checkout. Distinguished
|
||||||
|
# from the foreign-checkout case below because the fix differs — move it
|
||||||
|
# aside and re-run install.sh, rather than re-point a link.
|
||||||
|
if [ ! -L "$dir" ] && [ -d "$dir" ]; then
|
||||||
|
add FAIL unmanaged "$dir is a real directory, not a link into the checkout — it holds $(count_skills "$dir") unmanaged skill(s); move it aside and re-run install.sh"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
# Resolve to a physical path and confirm it lands inside THIS checkout.
|
# Resolve to a physical path and confirm it lands inside THIS checkout.
|
||||||
# A link that resolves to a different checkout is the dangerous case: it
|
# A link that resolves to a different checkout is the dangerous case: it
|
||||||
# works, so nothing complains, while serving stale content.
|
# works, so nothing complains, while serving stale content.
|
||||||
|
|||||||
+33
-38
@@ -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, buildctl 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, shared buildctl image-build script, 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
|
||||||
@@ -133,44 +133,39 @@ jobs:
|
|||||||
echo "version-tag=${REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
echo "version-tag=${REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# infra#309: do NOT paste a build implementation here. The estate has
|
||||||
|
# exactly one, mathias/infra's ci-templates/build-image.sh, and each
|
||||||
|
# repo carries a byte-identical copy at .gitea/build-image.sh that a
|
||||||
|
# drift gate keeps current.
|
||||||
|
#
|
||||||
|
# Copying the implementation is what made the buildah->buildctl
|
||||||
|
# migration (infra#241) an eleven-repo sprint, and what left this very
|
||||||
|
# skill handing out the broken version for weeks after the app repos
|
||||||
|
# were fixed. Per-repo differences are INPUTS, not edits to the copy.
|
||||||
|
#
|
||||||
|
# To adopt in a new repo:
|
||||||
|
# 1. add the repo to mathias/infra ci-templates/adopters.txt
|
||||||
|
# 2. run `task ci:sync` in mathias/infra -- it writes the copy
|
||||||
|
# 3. commit .gitea/build-image.sh in your repo
|
||||||
|
# 4. call it as below
|
||||||
|
#
|
||||||
|
# Skipping step 1 leaves the copy unmanaged: it works today and falls
|
||||||
|
# silently behind the next time the canonical file changes.
|
||||||
|
#
|
||||||
|
# Inputs: IMAGE (required, usually the workflow-level env), SHA_TAG,
|
||||||
|
# VERSION_TAG, GIT_SHA, IMAGE_SOURCE, BUILD_ARGS, EXTRA_LABELS,
|
||||||
|
# CONTEXT, DOCKERFILE_DIR, DOCKERFILE_NAME, PUSH_LATEST. Read the
|
||||||
|
# canonical file's header for the full list.
|
||||||
|
#
|
||||||
|
# `bash <script>`, not a direct exec: a file written through the Gitea
|
||||||
|
# API lands 0644, and CI that depends on a file mode is a trap.
|
||||||
- name: Build and push to local registry
|
- name: Build and push to local registry
|
||||||
run: |
|
env:
|
||||||
set -e
|
SHA_TAG: ${{ steps.meta.outputs.sha-tag }}
|
||||||
# buildctl, NOT buildah (infra#241). The runner is a pod with
|
VERSION_TAG: ${{ steps.meta.outputs.version-tag }}
|
||||||
# `capabilities: drop [ALL]` and `allowPrivilegeEscalation: false`,
|
GIT_SHA: ${{ github.sha }}
|
||||||
# so rootless buildah cannot remap UID/GID for a fresh base-image
|
IMAGE_SOURCE: ${{ github.repositoryUrl }}
|
||||||
# pull and the pod has no OCI runtime -- every `RUN` step fails.
|
run: bash .gitea/build-image.sh
|
||||||
# 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"
|
|
||||||
REF="${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.sha-tag }}"
|
|
||||||
TAR_FILE="$(mktemp)"
|
|
||||||
trap 'rm -f "$TAR_FILE"' EXIT
|
|
||||||
|
|
||||||
buildctl --addr "$BUILDKIT_HOST" build \
|
|
||||||
--frontend dockerfile.v0 \
|
|
||||||
--local context=. \
|
|
||||||
--local dockerfile=. \
|
|
||||||
--opt label:org.opencontainers.image.revision="${{ github.sha }}" \
|
|
||||||
--opt label:org.opencontainers.image.source="${{ github.repositoryUrl }}" \
|
|
||||||
--output type=oci,dest="$TAR_FILE"
|
|
||||||
|
|
||||||
# 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}"
|
|
||||||
|
|
||||||
# No smoke test step. The one this skill used to recommend ran
|
# No smoke test step. The one this skill used to recommend ran
|
||||||
# `sudo k3s ctr run` against the host's containerd -- that worked when
|
# `sudo k3s ctr run` against the host's containerd -- that worked when
|
||||||
|
|||||||
@@ -112,6 +112,19 @@ mkdir -p "$f/home/.claude/skills"
|
|||||||
ln -sfn "$f/ck/skills/alpha" "$f/home/.claude/skills/alpha"
|
ln -sfn "$f/ck/skills/alpha" "$f/home/.claude/skills/alpha"
|
||||||
assert_fails "$f" 'legacy' 'leftover per-skill Claude symlinks are reported'
|
assert_fails "$f" 'legacy' 'leftover per-skill Claude symlinks are reported'
|
||||||
|
|
||||||
|
# --- 7b. harness dir is a REAL directory, not a link into the checkout -------
|
||||||
|
# Found on flamingo 2026-08-26: ~/.config/crush/skills held real directories
|
||||||
|
# from a pre-plugin install. The old message read "resolves to
|
||||||
|
# <path>, outside the active checkout" — naming the directory as its own
|
||||||
|
# resolution target, which is true but useless. It must say the dir is not a
|
||||||
|
# link at all, because the fix (move it aside, re-run install.sh) is different
|
||||||
|
# from the fix for a link into a foreign checkout.
|
||||||
|
f=$(new_fixture realdir)
|
||||||
|
mkdir -p "$f/home/.agents" "$f/home/.config/crush/skills/alpha"
|
||||||
|
ln -sfn "$f/ck/skills" "$f/home/.agents/skills"
|
||||||
|
printf -- '---\nname: alpha\ndescription: a\n---\n' > "$f/home/.config/crush/skills/alpha/SKILL.md"
|
||||||
|
assert_fails "$f" 'not a link' 'real directory is reported as unmanaged, not as "outside"'
|
||||||
|
|
||||||
# --- 7. dangling link inside a harness dir (not the canonical link itself) --
|
# --- 7. dangling link inside a harness dir (not the canonical link itself) --
|
||||||
# Exercises the per-entry scan rather than the canonical-link check: this is
|
# Exercises the per-entry scan rather than the canonical-link check: this is
|
||||||
# the shape the 243 dead links actually had.
|
# the shape the 243 dead links actually had.
|
||||||
|
|||||||
Reference in New Issue
Block a user