ci: align gitea workflows with agent kit
This commit is contained in:
@@ -11,6 +11,11 @@ on:
|
||||
jobs:
|
||||
test-and-image:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
REGISTRY_HOST: git.wilkensxl.de
|
||||
REGISTRY_NAMESPACE: mrsphay
|
||||
IMAGE_NAME: intelligence-terminal
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -31,12 +36,17 @@ jobs:
|
||||
run: docker compose config
|
||||
|
||||
- name: Build Docker image
|
||||
run: docker build -t git.wilkensxl.de/mrsphay/intelligence-terminal:${{ github.sha }} .
|
||||
run: docker build -t "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}:${GITHUB_SHA}" .
|
||||
|
||||
- name: Publish Docker image
|
||||
if: ${{ secrets.REGISTRY_TOKEN != '' }}
|
||||
if: ${{ env.REGISTRY_TOKEN != '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.wilkensxl.de -u "${{ github.repository_owner }}" --password-stdin
|
||||
docker tag git.wilkensxl.de/mrsphay/intelligence-terminal:${{ github.sha }} git.wilkensxl.de/mrsphay/intelligence-terminal:latest
|
||||
docker push git.wilkensxl.de/mrsphay/intelligence-terminal:${{ github.sha }}
|
||||
docker push git.wilkensxl.de/mrsphay/intelligence-terminal:latest
|
||||
image="${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}"
|
||||
date_tag="$(date -u +%Y%m%d)"
|
||||
echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY_HOST}" -u "${REGISTRY_NAMESPACE}" --password-stdin
|
||||
docker tag "${image}:${GITHUB_SHA}" "${image}:latest"
|
||||
docker tag "${image}:${GITHUB_SHA}" "${image}:${date_tag}"
|
||||
docker push "${image}:${GITHUB_SHA}"
|
||||
docker push "${image}:latest"
|
||||
docker push "${image}:${date_tag}"
|
||||
|
||||
114
.gitea/workflows/dependency-check.yml
Normal file
114
.gitea/workflows/dependency-check.yml
Normal file
@@ -0,0 +1,114 @@
|
||||
name: Scheduled Dependency Check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "29 3 * * 2"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
dependency-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Detect project stack
|
||||
id: detect
|
||||
shell: bash
|
||||
run: |
|
||||
stacks=""
|
||||
|
||||
[ -f package.json ] && stacks="${stacks} node"
|
||||
{ [ -f pyproject.toml ] || [ -f requirements.txt ]; } && stacks="${stacks} python"
|
||||
[ -f Cargo.toml ] && stacks="${stacks} rust"
|
||||
[ -f go.mod ] && stacks="${stacks} go"
|
||||
{ [ -f Dockerfile ] || [ -f compose.yml ] || [ -f docker-compose.yml ]; } && stacks="${stacks} docker"
|
||||
|
||||
echo "stacks=${stacks:-generic}" >> "$GITHUB_OUTPUT"
|
||||
echo "Detected stacks:${stacks:- generic}"
|
||||
|
||||
- name: Node dependency report
|
||||
if: contains(steps.detect.outputs.stacks, 'node')
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then
|
||||
npm ci
|
||||
else
|
||||
npm install --package-lock-only --ignore-scripts
|
||||
fi
|
||||
|
||||
echo "Security audit:"
|
||||
npm audit --omit=dev --audit-level=high
|
||||
|
||||
echo
|
||||
echo "Outdated dependencies:"
|
||||
npm outdated || true
|
||||
|
||||
- name: Python dependency report
|
||||
if: contains(steps.detect.outputs.stacks, 'python')
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip pip-audit
|
||||
|
||||
echo "Security audit:"
|
||||
if [ -f requirements.txt ]; then
|
||||
pip-audit -r requirements.txt
|
||||
else
|
||||
pip-audit
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Outdated packages:"
|
||||
python -m pip list --outdated || true
|
||||
|
||||
- name: Rust dependency report
|
||||
if: contains(steps.detect.outputs.stacks, 'rust')
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install cargo-audit cargo-outdated --locked
|
||||
|
||||
echo "Security audit:"
|
||||
cargo audit
|
||||
|
||||
echo
|
||||
echo "Outdated crates:"
|
||||
cargo outdated || true
|
||||
|
||||
- name: Go dependency report
|
||||
if: contains(steps.detect.outputs.stacks, 'go')
|
||||
shell: bash
|
||||
run: |
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
|
||||
echo "Security audit:"
|
||||
govulncheck ./...
|
||||
|
||||
echo
|
||||
echo "Available dependency updates:"
|
||||
go list -u -m all || true
|
||||
|
||||
- name: Docker base image report
|
||||
if: contains(steps.detect.outputs.stacks, 'docker')
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Docker image references:"
|
||||
grep -RInE --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=build '^\s*FROM\s+' Dockerfile* . 2>/dev/null || true
|
||||
|
||||
echo
|
||||
echo "Review Docker base images manually for pinned versions, official sources, and current security status."
|
||||
|
||||
- name: Dependency guidance
|
||||
shell: bash
|
||||
run: |
|
||||
cat <<'EOF'
|
||||
Dependency check completed.
|
||||
|
||||
This workflow reports vulnerabilities and available updates. It does
|
||||
not modify dependency files, create pull requests, or publish packages.
|
||||
|
||||
Recommended manual follow-up:
|
||||
- update dependencies in a focused branch,
|
||||
- run the project test/build commands,
|
||||
- review lockfile diffs carefully,
|
||||
- document intentionally held versions.
|
||||
EOF
|
||||
133
.gitea/workflows/release-dry-run.yml
Normal file
133
.gitea/workflows/release-dry-run.yml
Normal file
@@ -0,0 +1,133 @@
|
||||
name: Release Dry Run
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release-dry-run:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Inspect release metadata
|
||||
shell: bash
|
||||
run: |
|
||||
missing=0
|
||||
|
||||
required_docs=(
|
||||
"README.md"
|
||||
"CHANGELOG.md"
|
||||
"SECURITY.md"
|
||||
"docs/release-checklist.md"
|
||||
)
|
||||
|
||||
for file in "${required_docs[@]}"; do
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "Missing release document: $file"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
|
||||
placeholder_paths=(README.md AGENTS.md .codex docs .gitea)
|
||||
placeholder_pattern='PROJECT_NAME|PROJECT_DESCRIPTION|REPOSITORY_OWNER|REPOSITORY_NAME|PACKAGE_NAME|ARTIFACT_NAME|ARTIFACT_OUTPUT_DIRECTORY|DOWNLOAD_URL|CI_URL|RELEASES_URL|BUILD_COMMAND|TEST_COMMAND|LINT_COMMAND|AUDIT_COMMAND|COMMIT_OR_VERSION'
|
||||
|
||||
for path in "${placeholder_paths[@]}"; do
|
||||
[ -e "$path" ] || continue
|
||||
if grep -RInE --exclude-dir=.git "$placeholder_pattern" "$path"; then
|
||||
echo "Unresolved template placeholders found."
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$missing" -eq 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Detect project stack
|
||||
id: detect
|
||||
shell: bash
|
||||
run: |
|
||||
stacks=""
|
||||
|
||||
[ -f package.json ] && stacks="${stacks} node"
|
||||
{ [ -f pyproject.toml ] || [ -f requirements.txt ]; } && stacks="${stacks} python"
|
||||
[ -f Cargo.toml ] && stacks="${stacks} rust"
|
||||
[ -f go.mod ] && stacks="${stacks} go"
|
||||
|
||||
echo "stacks=${stacks:-generic}" >> "$GITHUB_OUTPUT"
|
||||
echo "Detected stacks:${stacks:- generic}"
|
||||
|
||||
- name: Node release checks
|
||||
if: contains(steps.detect.outputs.stacks, 'node')
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then
|
||||
npm ci
|
||||
else
|
||||
npm install
|
||||
fi
|
||||
|
||||
node -e "const p=require('./package.json'); if(!p.name||!p.version){throw new Error('package.json needs name and version')}; console.log(p.name+'@'+p.version)"
|
||||
|
||||
npm run lint --if-present
|
||||
npm test --if-present
|
||||
npm run build --if-present
|
||||
npm run release:check --if-present
|
||||
|
||||
- name: Python release checks
|
||||
if: contains(steps.detect.outputs.stacks, 'python')
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
if [ -f requirements.txt ]; then
|
||||
python -m pip install -r requirements.txt
|
||||
fi
|
||||
|
||||
if [ -f pyproject.toml ]; then
|
||||
python -m pip install build
|
||||
python -m build
|
||||
else
|
||||
echo "No pyproject.toml found; skipped Python package build."
|
||||
fi
|
||||
|
||||
- name: Rust release checks
|
||||
if: contains(steps.detect.outputs.stacks, 'rust')
|
||||
shell: bash
|
||||
run: |
|
||||
cargo test
|
||||
cargo build --release
|
||||
|
||||
- name: Go release checks
|
||||
if: contains(steps.detect.outputs.stacks, 'go')
|
||||
shell: bash
|
||||
run: |
|
||||
go test ./...
|
||||
go build ./...
|
||||
|
||||
- name: Artifact report
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Potential release artifacts:"
|
||||
find . \
|
||||
-path ./.git -prune -o \
|
||||
-path ./node_modules -prune -o \
|
||||
-path './dist/*' -type f -print -o \
|
||||
-path './build/*' -type f -print -o \
|
||||
-path './release/*' -type f -print -o \
|
||||
-path './target/release/*' -type f -print \
|
||||
| sed 's#^\./##' \
|
||||
| head -200
|
||||
|
||||
cat <<'EOF'
|
||||
|
||||
Release dry run completed.
|
||||
|
||||
This workflow verifies release readiness. It does not create tags,
|
||||
releases, packages, or upload artifacts.
|
||||
EOF
|
||||
139
.gitea/workflows/repo-cleanup.yml
Normal file
139
.gitea/workflows/repo-cleanup.yml
Normal file
@@ -0,0 +1,139 @@
|
||||
name: Scheduled Repository Cleanup Check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "43 3 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
cleanup-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check ignored and untracked generated files
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Ignored files that would be skipped by git:"
|
||||
git status --ignored --short || true
|
||||
|
||||
echo
|
||||
echo "Tracked generated files check:"
|
||||
generated_patterns=(
|
||||
'(^|/)node_modules/'
|
||||
'(^|/)dist/'
|
||||
'(^|/)build/'
|
||||
'(^|/)out/'
|
||||
'(^|/)release/'
|
||||
'(^|/)target/'
|
||||
'(^|/)coverage/'
|
||||
'\.log$'
|
||||
'\.tmp$'
|
||||
'\.temp$'
|
||||
)
|
||||
|
||||
found=0
|
||||
tracked_files="$(git ls-files)"
|
||||
for pattern in "${generated_patterns[@]}"; do
|
||||
if echo "$tracked_files" | grep -Ei "$pattern"; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Generated files appear to be tracked. Review .gitignore and remove generated outputs from version control if appropriate."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check large tracked files
|
||||
shell: bash
|
||||
run: |
|
||||
limit_bytes="${LARGE_FILE_LIMIT_BYTES:-5242880}"
|
||||
found=0
|
||||
|
||||
while IFS= read -r file; do
|
||||
[ -f "$file" ] || continue
|
||||
size="$(wc -c < "$file")"
|
||||
if [ "$size" -gt "$limit_bytes" ]; then
|
||||
echo "${file} is ${size} bytes, above limit ${limit_bytes}."
|
||||
found=1
|
||||
fi
|
||||
done < <(git ls-files)
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Large tracked files found. Move release artifacts to packages/releases or document why they belong in git."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check local config and secret-prone files
|
||||
shell: bash
|
||||
run: |
|
||||
found=0
|
||||
|
||||
risky_patterns=(
|
||||
'^\.env$'
|
||||
'^\.env\.'
|
||||
'\.pfx$'
|
||||
'\.p12$'
|
||||
'\.pem$'
|
||||
'\.key$'
|
||||
'\.token$'
|
||||
'(^|/)secrets/'
|
||||
)
|
||||
|
||||
tracked_files="$(git ls-files)"
|
||||
for pattern in "${risky_patterns[@]}"; do
|
||||
if echo "$tracked_files" | grep -Ei "$pattern" | grep -vE '^\.env\.example$'; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Secret-prone local config files are tracked. Review immediately."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check stale branches
|
||||
shell: bash
|
||||
run: |
|
||||
git fetch --all --prune
|
||||
|
||||
protected='^(main|master|develop|dev|release|staging|production)$'
|
||||
cutoff="$(date -u -d '90 days ago' +%s)"
|
||||
found=0
|
||||
|
||||
while IFS='|' read -r branch timestamp; do
|
||||
branch="${branch#origin/}"
|
||||
[ "$branch" = "HEAD" ] && continue
|
||||
echo "$branch" | grep -Eq "$protected" && continue
|
||||
|
||||
if [ "$timestamp" -lt "$cutoff" ]; then
|
||||
echo "Stale remote branch candidate: ${branch}"
|
||||
found=1
|
||||
fi
|
||||
done < <(git for-each-ref refs/remotes/origin --format='%(refname:short)|%(committerdate:unix)')
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Stale branch candidates found. Review manually before deleting anything."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Cleanup guidance
|
||||
shell: bash
|
||||
run: |
|
||||
cat <<'EOF'
|
||||
Repository cleanup check completed.
|
||||
|
||||
This workflow reports cleanup candidates. It does not delete branches,
|
||||
packages, releases, or files automatically.
|
||||
|
||||
Recommended manual follow-up:
|
||||
- remove generated files from git,
|
||||
- update .gitignore,
|
||||
- move large artifacts to releases or package registry,
|
||||
- review stale branches,
|
||||
- document intentional exceptions.
|
||||
EOF
|
||||
174
.gitea/workflows/security-scan.yml
Normal file
174
.gitea/workflows/security-scan.yml
Normal file
@@ -0,0 +1,174 @@
|
||||
name: Scheduled Security Scan
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "17 3 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
security-scan:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Detect project stack
|
||||
id: detect
|
||||
shell: bash
|
||||
run: |
|
||||
stacks=""
|
||||
|
||||
[ -f package.json ] && stacks="${stacks} node"
|
||||
{ [ -f pyproject.toml ] || [ -f requirements.txt ]; } && stacks="${stacks} python"
|
||||
[ -f Cargo.toml ] && stacks="${stacks} rust"
|
||||
[ -f go.mod ] && stacks="${stacks} go"
|
||||
{ [ -f Dockerfile ] || [ -f compose.yml ] || [ -f docker-compose.yml ]; } && stacks="${stacks} docker"
|
||||
|
||||
echo "stacks=${stacks:-generic}" >> "$GITHUB_OUTPUT"
|
||||
echo "Detected stacks:${stacks:- generic}"
|
||||
|
||||
- name: Node production dependency audit
|
||||
if: contains(steps.detect.outputs.stacks, 'node')
|
||||
run: npm audit --omit=dev --audit-level=high
|
||||
|
||||
- name: Python dependency audit
|
||||
if: contains(steps.detect.outputs.stacks, 'python')
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip pip-audit
|
||||
if [ -f requirements.txt ]; then
|
||||
pip-audit -r requirements.txt
|
||||
else
|
||||
pip-audit
|
||||
fi
|
||||
|
||||
- name: Rust dependency audit
|
||||
if: contains(steps.detect.outputs.stacks, 'rust')
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install cargo-audit --locked
|
||||
cargo audit
|
||||
|
||||
- name: Go vulnerability scan
|
||||
if: contains(steps.detect.outputs.stacks, 'go')
|
||||
shell: bash
|
||||
run: |
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
govulncheck ./...
|
||||
|
||||
- name: Suspicious code pattern scan
|
||||
shell: bash
|
||||
run: |
|
||||
grep_excludes=(
|
||||
--exclude-dir=.git
|
||||
--exclude-dir=node_modules
|
||||
--exclude-dir=dist
|
||||
--exclude-dir=build
|
||||
--exclude-dir=release
|
||||
--exclude=security-scan.yml
|
||||
)
|
||||
|
||||
patterns=(
|
||||
'eval\s*\('
|
||||
'new Function\s*\('
|
||||
'dangerouslySetInnerHTML'
|
||||
'innerHTML\s*='
|
||||
'child_process'
|
||||
'exec\s*\('
|
||||
'spawn\s*\('
|
||||
'shell\.openExternal'
|
||||
'nodeIntegration:\s*true'
|
||||
'webSecurity:\s*false'
|
||||
'allowRunningInsecureContent:\s*true'
|
||||
'curl .*sh'
|
||||
'wget .*sh'
|
||||
)
|
||||
|
||||
found=0
|
||||
for pattern in "${patterns[@]}"; do
|
||||
if grep -RInE "${grep_excludes[@]}" "$pattern" .; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Suspicious code patterns were found. Review the matches above."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Secret and config leak scan
|
||||
shell: bash
|
||||
run: |
|
||||
grep_excludes=(
|
||||
--exclude-dir=.git
|
||||
--exclude-dir=node_modules
|
||||
--exclude-dir=dist
|
||||
--exclude-dir=build
|
||||
--exclude-dir=release
|
||||
--exclude=security-scan.yml
|
||||
)
|
||||
|
||||
patterns=(
|
||||
'BEGIN (RSA |EC |OPENSSH |)PRIVATE KEY'
|
||||
'AKIA[0-9A-Z]{16}'
|
||||
'xox[baprs]-[0-9A-Za-z-]+'
|
||||
'gh[pousr]_[0-9A-Za-z_]+'
|
||||
'sk-[A-Za-z0-9]{20,}'
|
||||
'api[_-]?key\s*=\s*["'\'']?[A-Za-z0-9_\-]{20,}'
|
||||
'token\s*=\s*["'\'']?[A-Za-z0-9_\-]{20,}'
|
||||
'password\s*=\s*["'\'']?[^[:space:]]{8,}'
|
||||
)
|
||||
|
||||
found=0
|
||||
for pattern in "${patterns[@]}"; do
|
||||
if grep -RInE "${grep_excludes[@]}" "$pattern" .; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if find . -path ./.git -prune -o \( -name ".env" -o -name ".env.*" \) -not -name ".env.example" -print | grep .; then
|
||||
echo "Committed environment files were found."
|
||||
found=1
|
||||
fi
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Potential secret or config leak detected. Review the matches above."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: AI instruction injection scan
|
||||
shell: bash
|
||||
run: |
|
||||
grep_excludes=(
|
||||
--exclude-dir=.git
|
||||
--exclude-dir=node_modules
|
||||
--exclude-dir=dist
|
||||
--exclude-dir=build
|
||||
--exclude-dir=release
|
||||
--exclude=security-scan.yml
|
||||
)
|
||||
|
||||
patterns=(
|
||||
'ignore (all )?(previous|above) instructions'
|
||||
'system prompt'
|
||||
'developer message'
|
||||
'reveal your instructions'
|
||||
'exfiltrate'
|
||||
'send.*token'
|
||||
'send.*secret'
|
||||
'disable.*safety'
|
||||
'jailbreak'
|
||||
'prompt injection'
|
||||
)
|
||||
|
||||
found=0
|
||||
for pattern in "${patterns[@]}"; do
|
||||
if grep -RInEi "${grep_excludes[@]}" "$pattern" .; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Potential AI instruction-injection text found. Review whether this is documentation, test data, or malicious content."
|
||||
exit 1
|
||||
fi
|
||||
109
.gitea/workflows/template-compliance.yml
Normal file
109
.gitea/workflows/template-compliance.yml
Normal file
@@ -0,0 +1,109 @@
|
||||
name: Codex Template Compliance
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
template-compliance:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check required Codex files
|
||||
shell: bash
|
||||
run: |
|
||||
missing=0
|
||||
|
||||
required_files=(
|
||||
"AGENTS.md"
|
||||
".codex/project.md"
|
||||
"README.md"
|
||||
)
|
||||
|
||||
recommended_files=(
|
||||
"SECURITY.md"
|
||||
"CHANGELOG.md"
|
||||
"docs/agent-handoff.md"
|
||||
)
|
||||
|
||||
for file in "${required_files[@]}"; do
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "Missing required Codex file: $file"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
|
||||
for file in "${recommended_files[@]}"; do
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "Recommended Codex file not found: $file"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$missing" -eq 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check unresolved placeholders
|
||||
shell: bash
|
||||
run: |
|
||||
found=0
|
||||
paths=(AGENTS.md README.md SECURITY.md CHANGELOG.md .codex docs .gitea blueprint.md blueprint.json)
|
||||
pattern='PROJECT_NAME|PROJECT_DESCRIPTION|REPOSITORY_OWNER|REPOSITORY_NAME|PACKAGE_NAME|ARTIFACT_NAME|ARTIFACT_OUTPUT_DIRECTORY|AUTHOR_NAME|PROJECT_STACK|DOWNLOAD_URL|CI_URL|RELEASES_URL|BUILD_COMMAND|TEST_COMMAND|LINT_COMMAND|AUDIT_COMMAND|README_COMMAND|INSTALL_COMMAND|DEV_COMMAND|PACKAGE_MANAGER|PROJECT_VERSION|COMMIT_OR_VERSION'
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
[ -e "$path" ] || continue
|
||||
if grep -RInE --exclude-dir=.git "$pattern" "$path"; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" -eq 1 ]; then
|
||||
echo "Unresolved template placeholders found. Replace real values or mark genuinely unknown values as PENDING."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check README divider convention
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f blueprint.md ] || [ -f blueprint.json ]; then
|
||||
if ! grep -q 'template:section-line' blueprint.md 2>/dev/null; then
|
||||
echo "README blueprint exists but does not use {{ template:section-line }}."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Check workflow baseline
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Detected Gitea workflows:"
|
||||
find .gitea/workflows -maxdepth 1 -type f -name '*.yml' -print 2>/dev/null || true
|
||||
|
||||
if [ ! -f ".gitea/workflows/security-scan.yml" ]; then
|
||||
echo "Recommended workflow missing: .gitea/workflows/security-scan.yml"
|
||||
fi
|
||||
|
||||
if [ ! -f ".gitea/workflows/repo-cleanup.yml" ]; then
|
||||
echo "Recommended workflow missing: .gitea/workflows/repo-cleanup.yml"
|
||||
fi
|
||||
|
||||
- name: Compliance guidance
|
||||
shell: bash
|
||||
run: |
|
||||
cat <<'EOF'
|
||||
Codex template compliance check completed.
|
||||
|
||||
This workflow verifies agent context and template hygiene. It does
|
||||
not change files automatically.
|
||||
|
||||
Recommended manual follow-up:
|
||||
- add missing required Codex context files,
|
||||
- replace unresolved placeholders,
|
||||
- keep README blueprint and README output aligned,
|
||||
- document intentional exceptions in .codex/project.md.
|
||||
EOF
|
||||
Reference in New Issue
Block a user