-
Notifications
You must be signed in to change notification settings - Fork 0
124 lines (109 loc) · 4.81 KB
/
Copy pathrelease-module.yml
File metadata and controls
124 lines (109 loc) · 4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
name: Release (reusable)
# THE canonical release procedure for every acks-* module. Module repos call
# this via a thin release.yml referencing @main, so changes here propagate to
# all modules automatically — edit this file, never the callers.
#
# dry_run (manual "Run workflow" in a module) builds and validates everything
# but skips the tag check and publishing.
on:
workflow_call:
inputs:
dry_run:
description: Build and validate without tag-checking or publishing
type: boolean
required: false
default: false
jobs:
build-release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Verify tag matches module.json version
if: ${{ !inputs.dry_run }}
run: |
MANIFEST_VERSION=$(node -p "require('./module.json').version")
TAG_VERSION="${GITHUB_REF_NAME#v}"
echo "manifest=$MANIFEST_VERSION tag=$TAG_VERSION"
if [ "$MANIFEST_VERSION" != "$TAG_VERSION" ]; then
echo "::error::module.json version ($MANIFEST_VERSION) does not match tag ($TAG_VERSION)"
exit 1
fi
- name: Install dev dependencies
run: npm ci
- name: Build compendium packs
run: npm run build:packs --if-present
# IP gate, part 1 of 2 — scans the working tree. continue-on-error so the
# quarantine step below always gets to run; a leak must never fall through
# to a plain red X that leaves the repo public.
- name: IP leak scan (tree)
id: ipscan_tree
continue-on-error: true
run: node tools/ip-scan.mjs
- name: Validate scripts, templates, JSON, and packs
if: ${{ steps.ipscan_tree.outcome == 'success' }}
run: npm run validate --if-present
- name: Run logic tests
run: npm run test --if-present
- name: Verify every declared pack exists
run: |
node -e '
const fs = require("fs");
const m = require("./module.json");
let missing = false;
for (const p of m.packs ?? []) {
if (!fs.existsSync(p.path + "/CURRENT")) {
console.error(`::error::declared pack "${p.name}" is missing its compiled LevelDB at ${p.path}`);
missing = true;
}
}
if (missing) process.exit(1);
'
- name: Create module.zip
run: |
# Ship-by-default: everything the module needs at runtime is included
# automatically (docs/, ruledata/, future dirs). The -x list names
# dev-only paths; extend it only for new DEV-ONLY content.
zip -r module.zip . \
-x '.git/*' '.github/*' '.claude/*' 'node_modules/*' \
'packs/_source/*' 'tools/*' \
'package.json' 'package-lock.json' \
'.gitignore' '.gitattributes' 'CLAUDE.md' 'module.zip'
# IP gate, part 2 of 2 — scans what is actually about to be published,
# not just what is in the tree. Catches anything the zip step sweeps in.
- name: IP leak scan (release artifact)
id: ipscan_zip
continue-on-error: true
run: |
rm -rf /tmp/ipscan && mkdir -p /tmp/ipscan
unzip -q module.zip -d /tmp/ipscan
node tools/ip-scan.mjs /tmp/ipscan
# Quarantine, not blockade: the push already landed and the work is safe
# on the remote. What we withhold is *exposure* — the repo drops to
# private and no release assets are published until the leak is cleared.
- name: Quarantine repository on leak
if: ${{ steps.ipscan_tree.outcome == 'failure' || steps.ipscan_zip.outcome == 'failure' }}
env:
GH_TOKEN: ${{ secrets.IP_GATE_TOKEN }}
run: |
echo "::error::IP leak scan failed — withholding release and taking $GITHUB_REPOSITORY private."
if [ -z "$GH_TOKEN" ]; then
echo "::error::Secret IP_GATE_TOKEN is not set, so visibility cannot be changed automatically."
echo "::error::ACT NOW — take $GITHUB_REPOSITORY private by hand, then clear the leak."
echo "::error::Add a PAT with admin:repo as secret IP_GATE_TOKEN to automate this."
exit 1
fi
gh repo edit "$GITHUB_REPOSITORY" --visibility private --accept-visibility-change-consequences
echo "::warning::$GITHUB_REPOSITORY is now PRIVATE. Clear the leak, then restore visibility deliberately."
exit 1
- name: Publish release
if: ${{ !inputs.dry_run && steps.ipscan_tree.outcome == 'success' && steps.ipscan_zip.outcome == 'success' }}
uses: softprops/action-gh-release@v2
with:
files: |
module.json
module.zip