Files
reverse-skill/.github/workflows/ci.yml
T

204 lines
7.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# reverse-skill CI:路由回归 + 结构一致性 + 供应链 pin gate + 冒烟
# 矩阵:windows-latest(原生 powershell 5.1) + ubuntu-latest(pwsh + powershell shim)
# 触发:所有分支(含 fork 的改进分支),PR 也触发
name: CI
on:
push:
pull_request:
jobs:
routing-tests:
name: routing tests (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# 脚本内部以 `powershell` 调用子进程;Linux runner 只有 pwsh,做个 shim
- name: powershell shim (linux)
if: runner.os == 'Linux'
shell: bash
run: sudo ln -sf "$(command -v pwsh)" /usr/local/bin/powershell
- name: Routing regression (163 cases)
shell: pwsh
run: ./skills/scripts/test-routing.ps1
- name: Routing coherence + supply-chain pin gate
shell: pwsh
run: ./skills/scripts/verify-routing-coherence.ps1
- name: Bootstrap supply-chain regression
shell: pwsh
run: ./skills/scripts/test-bootstrap-supply-chain.ps1
- name: Bootstrap supply-chain regression (Windows PowerShell 5.1)
if: runner.os == 'Windows'
shell: powershell
run: ./skills/scripts/test-bootstrap-supply-chain.ps1
- name: Smoke (verify + parse + quick route)
shell: pwsh
run: ./skills/scripts/smoke.ps1
- name: INDEX.md up-to-date check
shell: pwsh
run: ./skills/scripts/extract-summaries.ps1 -Check
- name: All JSON manifests valid
shell: pwsh
run: |
Get-Content skills/scripts/bootstrap-manifest.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
Get-Content kali/scripts/bootstrap-manifest.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
Get-Content skills/config/routing.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
Get-Content skills/tests/routing-benchmark.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
Write-Host "All JSON valid"
- name: Doc fact tables vs manifest (verify-doc-facts)
shell: pwsh
run: ./skills/scripts/verify-doc-facts.ps1
sh-syntax:
name: shell script syntax check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: bash -n all .sh
shell: bash
run: |
set -e
while IFS= read -r f; do
bash -n "$f"
echo "syntax OK: $f"
done < <(git ls-files '*.sh')
- name: Structured routing parity (Bash)
shell: bash
run: |
set -euo pipefail
bash skills/scripts/test-routing.sh
bash skills/scripts/test-bootstrap-manifest.sh
scratch="$(mktemp -d)"
trap 'rm -rf "$scratch"' EXIT
if bash skills/scripts/case-init.sh \
--hint "offline apk" \
--case-name "../case-escape" \
--package-root "$scratch/project" \
--preset offline-sample \
--sample "$scratch/sample.apk"; then
echo "case-init accepted an unsafe case name" >&2
exit 1
fi
if bash skills/scripts/case-init.sh \
--hint "authorized web review" \
--case-name "invalid-network" \
--package-root "$scratch/project" \
--auth-granted \
--network-profile "internet" \
--target-url "https://example.test/"; then
echo "case-init accepted an unsupported network profile" >&2
exit 1
fi
bash skills/scripts/case-init.sh \
--hint "authorized web review" \
--case-name "network-default" \
--package-root "$scratch/project" \
--auth-granted \
--target-url "https://example.test/"
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/network-default/scope.md"
grep -Eq '^- ready_for_act: true$' "$scratch/project/work/network-default/scope.md"
bash skills/scripts/case-guard.sh --case-root "$scratch/project/work/network-default"
bash skills/scripts/case-init.sh \
--hint "authorized web review" \
--case-name "uppercase-network" \
--package-root "$scratch/project" \
--auth-granted \
--network-profile "AUTHORIZED_TARGET_ONLY" \
--target-url "https://example.test/"
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/uppercase-network/scope.md"
bash skills/scripts/case-init.sh \
--hint "pending review" \
--case-name "guard-section" \
--package-root "$scratch/project" \
--target-url "https://example.test/"
cat >> "$scratch/project/work/guard-section/scope.md" <<'FAKE_FIELDS'
## notes
- status: granted
- mode: authorized_target_only
- ready_for_act: true
FAKE_FIELDS
if bash skills/scripts/case-guard.sh --case-root "$scratch/project/work/guard-section"; then
echo "case-guard accepted fields outside their contract sections" >&2
exit 1
fi
- name: PowerShell syntax check (PSParser, all tracked .ps1)
shell: pwsh
run: |
$files = git ls-files '*.ps1'
if (-not $files) { Write-Host 'No .ps1 files tracked'; exit 0 }
$failed = 0
foreach ($f in $files) {
$tokens = $null
$errors = $null
[System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path $f), [ref]$tokens, [ref]$errors) | Out-Null
if ($errors -and $errors.Count -gt 0) {
$failed++
Write-Host "::error file=$f::$($errors.Count) parse error(s)"
foreach ($e in $errors) {
Write-Host (" L{0}:{1} {2}" -f $e.Extent.StartLineNumber, $e.Extent.StartColumnNumber, $e.Message)
}
} else {
Write-Host "syntax OK: $f"
}
}
if ($failed -gt 0) { exit 1 }
leak-scan:
name: field-journal leak scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Scan field-journal for un-anonymized secrets
shell: pwsh
run: ./skills/scripts/scan-leaks.ps1 -Path skills/field-journal
case-contract:
name: case contract test (ctf-demo)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Review examples/ctf-demo under strict contract
shell: bash
run: python3 skills/case-review/scripts/review_case.py examples/ctf-demo --verify-hashes --strict
version-check:
name: version consistency
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: VERSION matches latest CHANGELOG release
shell: pwsh
run: |
$v = (Get-Content VERSION -Raw).Trim()
$cl = Get-Content CHANGELOG.md -Raw
$m = [regex]::Match($cl, '(?m)^## \[(\d+\.\d+\.\d+)\]')
if (-not $m.Success) { Write-Error 'No version header found in CHANGELOG'; exit 1 }
$latest = $m.Groups[1].Value
if ($v -ne $latest) {
Write-Error "VERSION ($v) does not match latest CHANGELOG release ($latest)"
exit 1
}
Write-Host "Version OK: $v"