code-foundry 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/scripts/init-repo.sh +6 -0
- package/.github/scripts/sync-template.sh +39 -0
- package/.github/template.yml +1 -0
- package/.github/template.yml.example +1 -0
- package/.github/workflows/reusable-security.yml +291 -0
- package/.github/workflows/test.yml +4 -168
- package/CHANGELOG.md +14 -0
- package/README.md +7 -1
- package/package.json +1 -1
- package/src/cli.mjs +5 -0
|
@@ -11,6 +11,7 @@ force=false
|
|
|
11
11
|
languages="${REPO_FOUNDRY_LANGUAGES:-auto}"
|
|
12
12
|
features="${REPO_FOUNDRY_FEATURES:-all}"
|
|
13
13
|
package_manager="${REPO_FOUNDRY_PACKAGE_MANAGER:-auto}"
|
|
14
|
+
runtime_repository="${REPO_FOUNDRY_RUNTIME_REPOSITORY:-0xPlayerOne/code-foundry}"
|
|
14
15
|
bootstrap=true
|
|
15
16
|
release_type="${REPO_FOUNDRY_RELEASE_TYPE:-auto}"
|
|
16
17
|
npm_publish="${REPO_FOUNDRY_NPM_PUBLISH:-false}"
|
|
@@ -37,6 +38,7 @@ Options:
|
|
|
37
38
|
--features LIST all or comma-separated optional features:
|
|
38
39
|
ci,codeql,security,test,draft-pr,release-pr,release,dependabot
|
|
39
40
|
--package-manager NAME auto, bun, pnpm, yarn, or npm
|
|
41
|
+
--runtime-repository OWNER/REPO Reusable workflow runtime repository
|
|
40
42
|
--release-type NAME auto, node, python, rust, or simple
|
|
41
43
|
--license NAME agpl-3.0-or-later, mit, preserve, or none
|
|
42
44
|
--license-file PATH Use an exact custom license file
|
|
@@ -63,6 +65,7 @@ while [ "$#" -gt 0 ]; do
|
|
|
63
65
|
--languages) languages="${2:?missing language list}"; shift 2 ;;
|
|
64
66
|
--features) features="${2:?missing feature list}"; shift 2 ;;
|
|
65
67
|
--package-manager) package_manager="${2:?missing package manager}"; shift 2 ;;
|
|
68
|
+
--runtime-repository) runtime_repository="${2:?missing runtime repository}"; shift 2 ;;
|
|
66
69
|
--release-type) release_type="${2:?missing release type}"; shift 2 ;;
|
|
67
70
|
--license) license="${2:?missing license}"; shift 2 ;;
|
|
68
71
|
--license-file) license_file="${2:?missing license file}"; shift 2 ;;
|
|
@@ -108,6 +111,7 @@ sync_args=(
|
|
|
108
111
|
--languages "$languages"
|
|
109
112
|
--features "$features"
|
|
110
113
|
--package-manager "$package_manager"
|
|
114
|
+
--runtime-repository "$runtime_repository"
|
|
111
115
|
--license "$license"
|
|
112
116
|
)
|
|
113
117
|
if [ -n "$license_file" ]; then sync_args+=(--license-file "$license_file"); fi
|
|
@@ -127,6 +131,7 @@ profile="$(awk -F': ' '/^profile:/ {print $2; exit}' .github/template.yml 2>/dev
|
|
|
127
131
|
languages="$(awk -F': ' '/^languages:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
128
132
|
features="$(awk -F': ' '/^features:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
129
133
|
package_manager="$(awk -F': ' '/^package_manager:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
134
|
+
runtime_repository="$(awk -F': ' '/^runtime_repository:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
130
135
|
release_type="$(awk -F': ' '/^release_type:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
131
136
|
npm_publish="$(awk -F': ' '/^npm_publish:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
132
137
|
license="$(awk -F': ' '/^license:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
|
|
@@ -139,6 +144,7 @@ license="$(awk -F': ' '/^license:/ {print $2; exit}' .github/template.yml 2>/dev
|
|
|
139
144
|
printf 'languages: %s\n' "$languages"
|
|
140
145
|
printf 'features: %s\n' "$features"
|
|
141
146
|
printf 'package_manager: %s\n' "$package_manager"
|
|
147
|
+
printf 'runtime_repository: %s\n' "$runtime_repository"
|
|
142
148
|
printf 'release_type: %s\n' "$release_type"
|
|
143
149
|
printf 'npm_publish: %s\n' "$npm_publish"
|
|
144
150
|
printf 'license: %s\n' "$license"
|
|
@@ -13,6 +13,7 @@ Options:
|
|
|
13
13
|
--languages LIST auto or comma-separated: typescript,rust,python,solidity
|
|
14
14
|
--features LIST all or comma-separated standard features
|
|
15
15
|
--package-manager NAME auto, bun, pnpm, yarn, or npm
|
|
16
|
+
--runtime-repository OWNER/REPO Reusable workflow runtime repository
|
|
16
17
|
--license NAME preserve, agpl-3.0-or-later, mit, or none
|
|
17
18
|
--license-file PATH Use an exact custom license file
|
|
18
19
|
--check Preview changes (default)
|
|
@@ -40,6 +41,9 @@ features_set=false
|
|
|
40
41
|
package_manager="${REPO_FOUNDRY_PACKAGE_MANAGER:-}"
|
|
41
42
|
package_manager_set=false
|
|
42
43
|
[ -n "${REPO_FOUNDRY_PACKAGE_MANAGER:-}" ] && package_manager_set=true
|
|
44
|
+
runtime_repository="${REPO_FOUNDRY_RUNTIME_REPOSITORY:-}"
|
|
45
|
+
runtime_repository_set=false
|
|
46
|
+
[ -n "${REPO_FOUNDRY_RUNTIME_REPOSITORY:-}" ] && runtime_repository_set=true
|
|
43
47
|
template_ref=""
|
|
44
48
|
release_type="${REPO_FOUNDRY_RELEASE_TYPE:-auto}"
|
|
45
49
|
npm_publish="${REPO_FOUNDRY_NPM_PUBLISH:-false}"
|
|
@@ -104,6 +108,7 @@ while [ "$#" -gt 0 ]; do
|
|
|
104
108
|
--languages) languages="${2:?missing language list}"; languages_set=true; shift 2 ;;
|
|
105
109
|
--features) features="${2:?missing feature list}"; features_set=true; shift 2 ;;
|
|
106
110
|
--package-manager) package_manager="${2:?missing package manager}"; package_manager_set=true; shift 2 ;;
|
|
111
|
+
--runtime-repository) runtime_repository="${2:?missing runtime repository}"; runtime_repository_set=true; shift 2 ;;
|
|
107
112
|
--license) license="${2:?missing license}"; license_set=true; shift 2 ;;
|
|
108
113
|
--license-file) license_file="${2:?missing license file}"; shift 2 ;;
|
|
109
114
|
--check) mode="check"; shift ;;
|
|
@@ -132,6 +137,9 @@ if [ -f .github/template.yml ]; then
|
|
|
132
137
|
if [ "$package_manager_set" = false ]; then
|
|
133
138
|
package_manager="$(awk -F': ' '/^package_manager:/ {print $2; exit}' .github/template.yml)"
|
|
134
139
|
fi
|
|
140
|
+
if [ "$runtime_repository_set" = false ]; then
|
|
141
|
+
runtime_repository="$(awk -F': ' '/^runtime_repository:/ {print $2; exit}' .github/template.yml)"
|
|
142
|
+
fi
|
|
135
143
|
template_ref="$(awk -F': ' '/^template:/ {print $2; exit}' .github/template.yml)"
|
|
136
144
|
if [ "$release_type_set" != true ]; then
|
|
137
145
|
configured_release_type="$(awk -F': ' '/^release_type:/ {print $2; exit}' .github/template.yml)"
|
|
@@ -147,6 +155,18 @@ if [ -f .github/template.yml ]; then
|
|
|
147
155
|
fi
|
|
148
156
|
fi
|
|
149
157
|
[ -n "$package_manager" ] || package_manager=auto
|
|
158
|
+
if [ -z "$runtime_repository" ]; then
|
|
159
|
+
source_repository="$source"
|
|
160
|
+
if [ -d "$source" ]; then
|
|
161
|
+
source_repository="$(git -C "$source" remote get-url origin 2>/dev/null || true)"
|
|
162
|
+
fi
|
|
163
|
+
runtime_repository="$(printf '%s\n' "$source_repository" | sed -nE 's#.*github\.com[:/]([^/]+/[^/.]+)(\.git)?$#\1#p')"
|
|
164
|
+
fi
|
|
165
|
+
[ -n "$runtime_repository" ] || runtime_repository="0xPlayerOne/code-foundry"
|
|
166
|
+
case "$runtime_repository" in
|
|
167
|
+
*/*) ;;
|
|
168
|
+
*) printf 'Runtime repository must be OWNER/REPO: %s\n' "$runtime_repository" >&2; exit 2 ;;
|
|
169
|
+
esac
|
|
150
170
|
case "$package_manager" in
|
|
151
171
|
auto|bun|pnpm|yarn|npm) ;;
|
|
152
172
|
*) printf 'Unsupported package manager: %s\n' "$package_manager" >&2; exit 2 ;;
|
|
@@ -185,6 +205,7 @@ if [ -f "$template_root/.github/scripts/profile.sh" ]; then
|
|
|
185
205
|
REPO_FOUNDRY_LANGUAGES="$languages" \
|
|
186
206
|
REPO_FOUNDRY_FEATURES="$features" \
|
|
187
207
|
REPO_FOUNDRY_PACKAGE_MANAGER="$package_manager" \
|
|
208
|
+
REPO_FOUNDRY_RUNTIME_REPOSITORY="$runtime_repository" \
|
|
188
209
|
REPO_FOUNDRY_RELEASE_TYPE="$release_type" \
|
|
189
210
|
REPO_FOUNDRY_NPM_PUBLISH="$npm_publish" \
|
|
190
211
|
bash "$template_root/.github/scripts/profile.sh" detect --root "$PWD"
|
|
@@ -354,6 +375,23 @@ for file in "${files[@]}"; do
|
|
|
354
375
|
fi
|
|
355
376
|
done
|
|
356
377
|
|
|
378
|
+
# Reusable workflow callers must use a literal repository/ref. Render the
|
|
379
|
+
# selected runtime repository while leaving custom workflows untouched.
|
|
380
|
+
for file in .github/workflows/ci.yml .github/workflows/test.yml; do
|
|
381
|
+
[ -f "$file" ] || continue
|
|
382
|
+
if grep -q '0xPlayerOne/code-foundry' "$file"; then
|
|
383
|
+
changed=$((changed + 1))
|
|
384
|
+
if [ "$mode" = "check" ]; then
|
|
385
|
+
printf 'Would render runtime repository in %s\n' "$file"
|
|
386
|
+
else
|
|
387
|
+
rendered_workflow="$(mktemp)"
|
|
388
|
+
sed "s#0xPlayerOne/code-foundry#$runtime_repository#g" "$file" > "$rendered_workflow"
|
|
389
|
+
mv "$rendered_workflow" "$file"
|
|
390
|
+
printf 'Rendered runtime repository in %s\n' "$file"
|
|
391
|
+
fi
|
|
392
|
+
fi
|
|
393
|
+
done
|
|
394
|
+
|
|
357
395
|
write_license() {
|
|
358
396
|
local owner license_source
|
|
359
397
|
[ "$license" != preserve ] || return 0
|
|
@@ -526,6 +564,7 @@ if [ "$mode" = "apply" ]; then
|
|
|
526
564
|
if [ -n "$package_manager" ]; then
|
|
527
565
|
printf 'package_manager: %s\n' "$package_manager"
|
|
528
566
|
fi
|
|
567
|
+
printf 'runtime_repository: %s\n' "$runtime_repository"
|
|
529
568
|
printf 'release_type: %s\n' "$release_type"
|
|
530
569
|
printf 'npm_publish: %s\n' "$npm_publish"
|
|
531
570
|
printf 'license: %s\n' "$license"
|
package/.github/template.yml
CHANGED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
name: Code Foundry Security
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
runtime-repository:
|
|
7
|
+
description: Repository containing the Code Foundry runtime.
|
|
8
|
+
required: false
|
|
9
|
+
type: string
|
|
10
|
+
default: 0xPlayerOne/code-foundry
|
|
11
|
+
runtime-ref:
|
|
12
|
+
description: Code Foundry runtime tag or ref.
|
|
13
|
+
required: false
|
|
14
|
+
type: string
|
|
15
|
+
default: v0.9.0
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
env:
|
|
21
|
+
REPO_FOUNDRY_PROFILE: ${{ vars.REPO_FOUNDRY_PROFILE }}
|
|
22
|
+
REPO_FOUNDRY_LANGUAGES: ${{ vars.REPO_FOUNDRY_LANGUAGES }}
|
|
23
|
+
REPO_FOUNDRY_FEATURES: ${{ vars.REPO_FOUNDRY_FEATURES }}
|
|
24
|
+
REPO_FOUNDRY_PACKAGE_MANAGER: ${{ vars.REPO_FOUNDRY_PACKAGE_MANAGER }}
|
|
25
|
+
REPO_FOUNDRY_CACHE_PACKAGES: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
|
|
26
|
+
REPO_FOUNDRY_BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before || '' }}
|
|
27
|
+
|
|
28
|
+
concurrency:
|
|
29
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.head.ref || github.ref_name }}
|
|
30
|
+
cancel-in-progress: true
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
profile:
|
|
34
|
+
name: Profile
|
|
35
|
+
runs-on: ubuntu-slim
|
|
36
|
+
timeout-minutes: 10
|
|
37
|
+
outputs:
|
|
38
|
+
javascript: ${{ steps.profile.outputs.javascript }}
|
|
39
|
+
rust: ${{ steps.profile.outputs.rust }}
|
|
40
|
+
python: ${{ steps.profile.outputs.python }}
|
|
41
|
+
python_requirements: ${{ steps.profile.outputs.python_requirements }}
|
|
42
|
+
steps:
|
|
43
|
+
- name: Checkout
|
|
44
|
+
uses: actions/checkout@v7
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 2
|
|
47
|
+
filter: blob:none
|
|
48
|
+
sparse-checkout: |
|
|
49
|
+
.github
|
|
50
|
+
.mise.toml
|
|
51
|
+
mise.lock
|
|
52
|
+
.npmrc
|
|
53
|
+
.pnpmfile.cjs
|
|
54
|
+
.yarnrc*
|
|
55
|
+
**/package.json
|
|
56
|
+
**/bun.lock
|
|
57
|
+
**/bun.lockb
|
|
58
|
+
**/pnpm-lock.yaml
|
|
59
|
+
**/yarn.lock
|
|
60
|
+
**/package-lock.json
|
|
61
|
+
**/Cargo.toml
|
|
62
|
+
**/Cargo.lock
|
|
63
|
+
**/.cargo/**
|
|
64
|
+
**/pyproject.toml
|
|
65
|
+
**/requirements*.txt
|
|
66
|
+
**/setup.py
|
|
67
|
+
**/setup.cfg
|
|
68
|
+
**/Pipfile
|
|
69
|
+
**/Pipfile.lock
|
|
70
|
+
**/poetry.lock
|
|
71
|
+
**/uv.lock
|
|
72
|
+
sparse-checkout-cone-mode: false
|
|
73
|
+
- name: Runtime
|
|
74
|
+
uses: actions/checkout@v7
|
|
75
|
+
with:
|
|
76
|
+
repository: ${{ inputs.runtime-repository }}
|
|
77
|
+
ref: ${{ inputs.runtime-ref }}
|
|
78
|
+
path: .code-foundry
|
|
79
|
+
sparse-checkout: |
|
|
80
|
+
.github/actions
|
|
81
|
+
.github/scripts
|
|
82
|
+
- name: Install runtime
|
|
83
|
+
run: |
|
|
84
|
+
mkdir -p .github/actions .github/scripts
|
|
85
|
+
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
86
|
+
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
87
|
+
- name: Detect
|
|
88
|
+
id: profile
|
|
89
|
+
run: bash .github/scripts/security.sh profile >> "$GITHUB_OUTPUT"
|
|
90
|
+
|
|
91
|
+
dependency-audit-javascript:
|
|
92
|
+
name: Dependency Audit (JavaScript)
|
|
93
|
+
runs-on: ubuntu-slim
|
|
94
|
+
timeout-minutes: 20
|
|
95
|
+
steps:
|
|
96
|
+
- name: Checkout
|
|
97
|
+
uses: actions/checkout@v7
|
|
98
|
+
with:
|
|
99
|
+
filter: blob:none
|
|
100
|
+
sparse-checkout: |
|
|
101
|
+
.github
|
|
102
|
+
.mise.toml
|
|
103
|
+
mise.lock
|
|
104
|
+
.npmrc
|
|
105
|
+
.pnpmfile.cjs
|
|
106
|
+
.yarnrc*
|
|
107
|
+
**/package.json
|
|
108
|
+
**/bun.lock
|
|
109
|
+
**/bun.lockb
|
|
110
|
+
**/pnpm-lock.yaml
|
|
111
|
+
**/yarn.lock
|
|
112
|
+
**/package-lock.json
|
|
113
|
+
sparse-checkout-cone-mode: false
|
|
114
|
+
- name: Runtime
|
|
115
|
+
uses: actions/checkout@v7
|
|
116
|
+
with:
|
|
117
|
+
repository: ${{ inputs.runtime-repository }}
|
|
118
|
+
ref: ${{ inputs.runtime-ref }}
|
|
119
|
+
path: .code-foundry
|
|
120
|
+
sparse-checkout: |
|
|
121
|
+
.github/actions
|
|
122
|
+
.github/scripts
|
|
123
|
+
- name: Install runtime
|
|
124
|
+
run: |
|
|
125
|
+
mkdir -p .github/actions .github/scripts
|
|
126
|
+
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
127
|
+
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
128
|
+
- name: Detect
|
|
129
|
+
id: applicability
|
|
130
|
+
run: bash .github/scripts/security.sh should_run javascript >> "$GITHUB_OUTPUT"
|
|
131
|
+
- name: Setup
|
|
132
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
133
|
+
uses: ./.github/actions/setup
|
|
134
|
+
with:
|
|
135
|
+
mise-scope: javascript
|
|
136
|
+
cache-save: ${{ github.event_name != 'pull_request' }}
|
|
137
|
+
- name: Audit dependencies
|
|
138
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
139
|
+
run: bash .github/scripts/security.sh audit javascript
|
|
140
|
+
|
|
141
|
+
dependency-audit-rust:
|
|
142
|
+
name: Dependency Audit (Rust)
|
|
143
|
+
runs-on: ${{ vars.REPO_FOUNDRY_RUST_AUDIT_RUNNER || 'ubuntu-latest' }}
|
|
144
|
+
timeout-minutes: 20
|
|
145
|
+
steps:
|
|
146
|
+
- name: Checkout
|
|
147
|
+
uses: actions/checkout@v7
|
|
148
|
+
with:
|
|
149
|
+
filter: blob:none
|
|
150
|
+
sparse-checkout: |
|
|
151
|
+
.github
|
|
152
|
+
.mise.toml
|
|
153
|
+
mise.lock
|
|
154
|
+
**/Cargo.toml
|
|
155
|
+
**/Cargo.lock
|
|
156
|
+
**/.cargo/**
|
|
157
|
+
sparse-checkout-cone-mode: false
|
|
158
|
+
- name: Runtime
|
|
159
|
+
uses: actions/checkout@v7
|
|
160
|
+
with:
|
|
161
|
+
repository: ${{ inputs.runtime-repository }}
|
|
162
|
+
ref: ${{ inputs.runtime-ref }}
|
|
163
|
+
path: .code-foundry
|
|
164
|
+
sparse-checkout: |
|
|
165
|
+
.github/actions
|
|
166
|
+
.github/scripts
|
|
167
|
+
- name: Install runtime
|
|
168
|
+
run: |
|
|
169
|
+
mkdir -p .github/actions .github/scripts
|
|
170
|
+
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
171
|
+
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
172
|
+
- name: Detect
|
|
173
|
+
id: applicability
|
|
174
|
+
run: bash .github/scripts/security.sh should_run rust >> "$GITHUB_OUTPUT"
|
|
175
|
+
- name: Check Rust
|
|
176
|
+
id: system-rust
|
|
177
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
178
|
+
shell: bash
|
|
179
|
+
run: |
|
|
180
|
+
if command -v cargo >/dev/null 2>&1 && command -v rustc >/dev/null 2>&1; then
|
|
181
|
+
cargo --version
|
|
182
|
+
rustc --version
|
|
183
|
+
echo 'available=true' >> "$GITHUB_OUTPUT"
|
|
184
|
+
else
|
|
185
|
+
echo 'available=false' >> "$GITHUB_OUTPUT"
|
|
186
|
+
fi
|
|
187
|
+
- name: Setup
|
|
188
|
+
if: >-
|
|
189
|
+
steps.applicability.outputs.applicable == 'true' &&
|
|
190
|
+
steps.system-rust.outputs.available != 'true'
|
|
191
|
+
uses: ./.github/actions/setup
|
|
192
|
+
with:
|
|
193
|
+
mise-scope: rust
|
|
194
|
+
cache-save: ${{ github.event_name != 'pull_request' }}
|
|
195
|
+
- name: Install cargo-audit
|
|
196
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
197
|
+
uses: taiki-e/install-action@v2
|
|
198
|
+
with:
|
|
199
|
+
tool: cargo-audit
|
|
200
|
+
- name: Audit dependencies
|
|
201
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
202
|
+
run: bash .github/scripts/security.sh audit rust
|
|
203
|
+
|
|
204
|
+
dependency-audit-python:
|
|
205
|
+
name: Dependency Audit (Python) / ${{ matrix.requirement }}
|
|
206
|
+
needs: profile
|
|
207
|
+
if: >-
|
|
208
|
+
${{ needs.profile.result == 'success' &&
|
|
209
|
+
needs.profile.outputs.python == 'true' &&
|
|
210
|
+
needs.profile.outputs.python_requirements != '["none"]' }}
|
|
211
|
+
strategy:
|
|
212
|
+
fail-fast: false
|
|
213
|
+
max-parallel: 8
|
|
214
|
+
matrix:
|
|
215
|
+
requirement: ${{ fromJSON(needs.profile.outputs.python_requirements) }}
|
|
216
|
+
runs-on: ubuntu-slim
|
|
217
|
+
timeout-minutes: 20
|
|
218
|
+
env:
|
|
219
|
+
REPO_FOUNDRY_PYTHON_REQUIREMENT: ${{ matrix.requirement }}
|
|
220
|
+
steps:
|
|
221
|
+
- name: Checkout
|
|
222
|
+
uses: actions/checkout@v7
|
|
223
|
+
with:
|
|
224
|
+
filter: blob:none
|
|
225
|
+
sparse-checkout: |
|
|
226
|
+
.github
|
|
227
|
+
.mise.toml
|
|
228
|
+
mise.lock
|
|
229
|
+
**/pyproject.toml
|
|
230
|
+
**/requirements*.txt
|
|
231
|
+
**/setup.py
|
|
232
|
+
**/setup.cfg
|
|
233
|
+
**/Pipfile
|
|
234
|
+
**/Pipfile.lock
|
|
235
|
+
**/poetry.lock
|
|
236
|
+
**/uv.lock
|
|
237
|
+
sparse-checkout-cone-mode: false
|
|
238
|
+
- name: Runtime
|
|
239
|
+
uses: actions/checkout@v7
|
|
240
|
+
with:
|
|
241
|
+
repository: ${{ inputs.runtime-repository }}
|
|
242
|
+
ref: ${{ inputs.runtime-ref }}
|
|
243
|
+
path: .code-foundry
|
|
244
|
+
sparse-checkout: |
|
|
245
|
+
.github/actions
|
|
246
|
+
.github/scripts
|
|
247
|
+
- name: Install runtime
|
|
248
|
+
run: |
|
|
249
|
+
mkdir -p .github/actions .github/scripts
|
|
250
|
+
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
251
|
+
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
252
|
+
- name: Setup
|
|
253
|
+
uses: ./.github/actions/setup
|
|
254
|
+
with:
|
|
255
|
+
mise-scope: python
|
|
256
|
+
cache-save: ${{ github.event_name != 'pull_request' }}
|
|
257
|
+
- name: Audit dependencies
|
|
258
|
+
run: bash .github/scripts/security.sh audit python
|
|
259
|
+
|
|
260
|
+
dependency-audit-python-gate:
|
|
261
|
+
name: Dependency Audit (Python)
|
|
262
|
+
needs: [profile, dependency-audit-python]
|
|
263
|
+
if: always()
|
|
264
|
+
runs-on: ubuntu-slim
|
|
265
|
+
timeout-minutes: 5
|
|
266
|
+
steps:
|
|
267
|
+
- name: Gate
|
|
268
|
+
env:
|
|
269
|
+
PROFILE_RESULT: ${{ needs.profile.result }}
|
|
270
|
+
AUDIT_RESULT: ${{ needs.dependency-audit-python.result }}
|
|
271
|
+
run: |
|
|
272
|
+
if [ "$PROFILE_RESULT" != success ]; then
|
|
273
|
+
echo "Python audit profile failed: $PROFILE_RESULT" >&2
|
|
274
|
+
exit 1
|
|
275
|
+
fi
|
|
276
|
+
case "$AUDIT_RESULT" in
|
|
277
|
+
success|skipped) exit 0 ;;
|
|
278
|
+
*) echo "Python dependency audit failed: $AUDIT_RESULT" >&2; exit 1 ;;
|
|
279
|
+
esac
|
|
280
|
+
|
|
281
|
+
dependency-review:
|
|
282
|
+
name: Dependency Review
|
|
283
|
+
if: ${{ github.event_name == 'pull_request' && !github.event.repository.private }}
|
|
284
|
+
runs-on: ubuntu-slim
|
|
285
|
+
timeout-minutes: 10
|
|
286
|
+
steps:
|
|
287
|
+
- name: Review
|
|
288
|
+
uses: actions/dependency-review-action@v5
|
|
289
|
+
with:
|
|
290
|
+
fail-on-severity: high
|
|
291
|
+
license-check: true
|
|
@@ -10,172 +10,8 @@ on:
|
|
|
10
10
|
permissions:
|
|
11
11
|
contents: read
|
|
12
12
|
|
|
13
|
-
env:
|
|
14
|
-
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
15
|
-
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
|
16
|
-
REPO_FOUNDRY_PROFILE: ${{ vars.REPO_FOUNDRY_PROFILE }}
|
|
17
|
-
REPO_FOUNDRY_LANGUAGES: ${{ vars.REPO_FOUNDRY_LANGUAGES }}
|
|
18
|
-
REPO_FOUNDRY_FEATURES: ${{ vars.REPO_FOUNDRY_FEATURES }}
|
|
19
|
-
REPO_FOUNDRY_PACKAGE_MANAGER: ${{ vars.REPO_FOUNDRY_PACKAGE_MANAGER }}
|
|
20
|
-
REPO_FOUNDRY_CACHE_PACKAGES: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
|
|
21
|
-
REPO_FOUNDRY_CACHE_BUILD: ${{ vars.REPO_FOUNDRY_CACHE_BUILD || 'auto' }}
|
|
22
|
-
REPO_FOUNDRY_BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before || '' }}
|
|
23
|
-
|
|
24
|
-
concurrency:
|
|
25
|
-
group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.head.ref || github.ref_name }}
|
|
26
|
-
cancel-in-progress: true
|
|
27
|
-
|
|
28
13
|
jobs:
|
|
29
|
-
|
|
30
|
-
name:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
runs-on: ${{ vars.REPO_FOUNDRY_UNIT_RUNNER || 'ubuntu-slim' }}
|
|
34
|
-
timeout-minutes: 30
|
|
35
|
-
steps:
|
|
36
|
-
- name: Checkout
|
|
37
|
-
uses: actions/checkout@v7
|
|
38
|
-
with:
|
|
39
|
-
fetch-depth: 2
|
|
40
|
-
- name: Detect
|
|
41
|
-
id: applicability
|
|
42
|
-
run: bash .github/scripts/ci.sh task_profile unit >> "$GITHUB_OUTPUT"
|
|
43
|
-
- name: Setup
|
|
44
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
45
|
-
uses: ./.github/actions/setup
|
|
46
|
-
with:
|
|
47
|
-
install: true
|
|
48
|
-
install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
|
|
49
|
-
install-python: ${{ steps.applicability.outputs.python == 'true' }}
|
|
50
|
-
install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
|
|
51
|
-
cache-build: false
|
|
52
|
-
cache-environment: false
|
|
53
|
-
cache-packages: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
|
|
54
|
-
task: unit
|
|
55
|
-
task-javascript: ${{ steps.applicability.outputs.javascript }}
|
|
56
|
-
task-python: ${{ steps.applicability.outputs.python }}
|
|
57
|
-
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
58
|
-
- name: Unit
|
|
59
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
60
|
-
run: bash .github/scripts/ci.sh unit
|
|
61
|
-
- name: Upload coverage
|
|
62
|
-
if: >-
|
|
63
|
-
always() &&
|
|
64
|
-
steps.applicability.outputs.applicable == 'true' &&
|
|
65
|
-
hashFiles('coverage/**', 'htmlcov/**', '.coverage*', 'target/llvm-cov/**') != ''
|
|
66
|
-
uses: actions/upload-artifact@v7
|
|
67
|
-
with:
|
|
68
|
-
name: coverage-unit-${{ github.run_id }}
|
|
69
|
-
path: |
|
|
70
|
-
coverage/**
|
|
71
|
-
htmlcov/**
|
|
72
|
-
.coverage*
|
|
73
|
-
target/llvm-cov/**
|
|
74
|
-
compression-level: 1
|
|
75
|
-
if-no-files-found: ignore
|
|
76
|
-
retention-days: 14
|
|
77
|
-
|
|
78
|
-
integration:
|
|
79
|
-
name: Integration
|
|
80
|
-
runs-on: ubuntu-latest
|
|
81
|
-
timeout-minutes: 30
|
|
82
|
-
steps:
|
|
83
|
-
- name: Checkout
|
|
84
|
-
uses: actions/checkout@v7
|
|
85
|
-
with:
|
|
86
|
-
fetch-depth: 2
|
|
87
|
-
- name: Detect
|
|
88
|
-
id: applicability
|
|
89
|
-
run: bash .github/scripts/ci.sh task_profile integration >> "$GITHUB_OUTPUT"
|
|
90
|
-
- name: Setup
|
|
91
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
92
|
-
uses: ./.github/actions/setup
|
|
93
|
-
with:
|
|
94
|
-
install: true
|
|
95
|
-
install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
|
|
96
|
-
install-python: ${{ steps.applicability.outputs.python == 'true' }}
|
|
97
|
-
install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
|
|
98
|
-
cache-build: ${{ steps.applicability.outputs.rust == 'true' }}
|
|
99
|
-
cache-environment: false
|
|
100
|
-
cache-save: ${{ github.event_name == 'push' }}
|
|
101
|
-
task: integration
|
|
102
|
-
task-javascript: ${{ steps.applicability.outputs.javascript }}
|
|
103
|
-
task-python: ${{ steps.applicability.outputs.python }}
|
|
104
|
-
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
105
|
-
- name: Integration
|
|
106
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
107
|
-
run: bash .github/scripts/ci.sh integration
|
|
108
|
-
|
|
109
|
-
e2e:
|
|
110
|
-
name: E2E
|
|
111
|
-
runs-on: ubuntu-latest
|
|
112
|
-
timeout-minutes: 45
|
|
113
|
-
steps:
|
|
114
|
-
- name: Checkout
|
|
115
|
-
uses: actions/checkout@v7
|
|
116
|
-
with:
|
|
117
|
-
fetch-depth: 2
|
|
118
|
-
- name: Detect
|
|
119
|
-
id: applicability
|
|
120
|
-
run: bash .github/scripts/ci.sh task_profile e2e >> "$GITHUB_OUTPUT"
|
|
121
|
-
- name: Cache browser binaries
|
|
122
|
-
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.browser == 'true'
|
|
123
|
-
uses: ./.github/actions/cache
|
|
124
|
-
with:
|
|
125
|
-
save: ${{ github.event_name == 'push' }}
|
|
126
|
-
path: |
|
|
127
|
-
~/.cache/ms-playwright
|
|
128
|
-
~/.cache/Cypress
|
|
129
|
-
~/.cache/puppeteer
|
|
130
|
-
key: ${{ runner.os }}-e2e-browsers-${{ hashFiles('**/package.json', '**/bun.lock', '**/bun.lockb', '**/pnpm-lock.yaml', '**/yarn.lock', '**/package-lock.json', '**/playwright.config.*', '**/cypress.config.*') }}
|
|
131
|
-
restore-keys: |
|
|
132
|
-
${{ runner.os }}-e2e-browsers-
|
|
133
|
-
- name: Setup
|
|
134
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
135
|
-
uses: ./.github/actions/setup
|
|
136
|
-
with:
|
|
137
|
-
install: true
|
|
138
|
-
install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
|
|
139
|
-
install-python: ${{ steps.applicability.outputs.python == 'true' }}
|
|
140
|
-
install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
|
|
141
|
-
cache-build: false
|
|
142
|
-
cache-environment: false
|
|
143
|
-
cache-save: ${{ github.event_name == 'push' }}
|
|
144
|
-
task: e2e
|
|
145
|
-
task-javascript: ${{ steps.applicability.outputs.javascript }}
|
|
146
|
-
task-python: ${{ steps.applicability.outputs.python }}
|
|
147
|
-
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
148
|
-
- name: E2E
|
|
149
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
150
|
-
run: bash .github/scripts/ci.sh e2e
|
|
151
|
-
|
|
152
|
-
smoke:
|
|
153
|
-
name: Smoke
|
|
154
|
-
runs-on: ubuntu-latest
|
|
155
|
-
timeout-minutes: 15
|
|
156
|
-
steps:
|
|
157
|
-
- name: Checkout
|
|
158
|
-
uses: actions/checkout@v7
|
|
159
|
-
with:
|
|
160
|
-
fetch-depth: 2
|
|
161
|
-
- name: Detect
|
|
162
|
-
id: applicability
|
|
163
|
-
run: bash .github/scripts/ci.sh task_profile smoke >> "$GITHUB_OUTPUT"
|
|
164
|
-
- name: Setup
|
|
165
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
166
|
-
uses: ./.github/actions/setup
|
|
167
|
-
with:
|
|
168
|
-
install: true
|
|
169
|
-
install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
|
|
170
|
-
install-python: ${{ steps.applicability.outputs.python == 'true' }}
|
|
171
|
-
install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
|
|
172
|
-
cache-build: false
|
|
173
|
-
cache-environment: false
|
|
174
|
-
cache-save: ${{ github.event_name == 'push' }}
|
|
175
|
-
task: smoke
|
|
176
|
-
task-javascript: ${{ steps.applicability.outputs.javascript }}
|
|
177
|
-
task-python: ${{ steps.applicability.outputs.python }}
|
|
178
|
-
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
179
|
-
- name: Smoke
|
|
180
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
181
|
-
run: bash .github/scripts/ci.sh smoke
|
|
14
|
+
test:
|
|
15
|
+
name: Test
|
|
16
|
+
uses: 0xPlayerOne/code-foundry/.github/workflows/reusable-test.yml@v0.8.0
|
|
17
|
+
secrets: inherit
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.9.0...v0.10.0) (2026-07-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **security:** add reusable security workflow runtime ([b21d014](https://github.com/0xPlayerOne/code-foundry/commit/b21d014e85cfcdef4181d488b1df91e3c950503b))
|
|
9
|
+
|
|
10
|
+
## [0.9.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.8.0...v0.9.0) (2026-07-28)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **init:** configure reusable workflow repository ([95d17e9](https://github.com/0xPlayerOne/code-foundry/commit/95d17e9a4af2e2075fcdc2c357af414876655fb3))
|
|
16
|
+
|
|
3
17
|
## [0.8.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.7.0...v0.8.0) (2026-07-28)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -36,6 +36,12 @@ npx code-foundry init --license agpl-3.0-or-later
|
|
|
36
36
|
npx code-foundry init --license-file ./legal/LICENSE.txt
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
Reusable workflow callers default to this package's public runtime. Use
|
|
40
|
+
`--runtime-repository OWNER/REPO` when initializing from an organization fork;
|
|
41
|
+
the selected repository is saved in `.github/template.yml` and rendered into
|
|
42
|
+
the small `ci.yml` and `test.yml` wrappers automatically. The equivalent
|
|
43
|
+
environment variable is `REPO_FOUNDRY_RUNTIME_REPOSITORY`.
|
|
44
|
+
|
|
39
45
|
Initialization defaults to AGPL for new repositories. Synchronization defaults
|
|
40
46
|
to `--license preserve`, so an existing repository's license is never replaced
|
|
41
47
|
unless you explicitly select a license or provide `--license-file`.
|
|
@@ -84,7 +90,7 @@ bash .github/scripts/init-repo.sh \
|
|
|
84
90
|
|
|
85
91
|
Supported profiles are `application`, `monorepo`, and `minimal`; use `auto` to detect one. Supported languages are `typescript`, `rust`, `python`, and `solidity`. Supported feature flags are `ci`, `codeql`, `security`, `test`, `draft-pr`, `release-pr`, `release`, and `dependabot`. Use `--prune` only when you explicitly want disabled standard workflows removed; custom workflows are always preserved. The selected profile is stored in `.github/template.yml`, which makes later syncs repeatable and lets workflows consume repository-specific settings without duplicating the template scripts.
|
|
86
92
|
|
|
87
|
-
Profile precedence is consistent everywhere: explicit CLI flags, then `REPO_FOUNDRY_*` GitHub repository variables/environment values, then `.github/template.yml`, then automatic detection and standard defaults. Useful repository variables include `REPO_FOUNDRY_PROFILE`, `REPO_FOUNDRY_LANGUAGES`, `REPO_FOUNDRY_FEATURES`, `REPO_FOUNDRY_PACKAGE_MANAGER`, `REPO_FOUNDRY_RUNNER`, `REPO_FOUNDRY_UNIT_RUNNER`, `REPO_FOUNDRY_CACHE_PACKAGES`, `REPO_FOUNDRY_CACHE_BUILD`, `REPO_FOUNDRY_COVERAGE_MINIMUM`, and `REPO_FOUNDRY_TURBO_REMOTE`. Use CLI flags for one-off initialization; use repository variables for local overrides that should not be committed.
|
|
93
|
+
Profile precedence is consistent everywhere: explicit CLI flags, then `REPO_FOUNDRY_*` GitHub repository variables/environment values, then `.github/template.yml`, then automatic detection and standard defaults. Useful repository variables include `REPO_FOUNDRY_PROFILE`, `REPO_FOUNDRY_LANGUAGES`, `REPO_FOUNDRY_FEATURES`, `REPO_FOUNDRY_PACKAGE_MANAGER`, `REPO_FOUNDRY_RUNTIME_REPOSITORY`, `REPO_FOUNDRY_RUNNER`, `REPO_FOUNDRY_UNIT_RUNNER`, `REPO_FOUNDRY_CACHE_PACKAGES`, `REPO_FOUNDRY_CACHE_BUILD`, `REPO_FOUNDRY_COVERAGE_MINIMUM`, and `REPO_FOUNDRY_TURBO_REMOTE`. Use CLI flags for one-off initialization; use repository variables for local overrides that should not be committed.
|
|
88
94
|
|
|
89
95
|
Inspect the resolved profile at any time with `bash .github/scripts/profile.sh detect`; use `profile.sh get KEY` when another script needs one setting.
|
|
90
96
|
|
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -22,6 +22,7 @@ Init/sync options:
|
|
|
22
22
|
--languages LIST auto or typescript,rust,python,solidity
|
|
23
23
|
--features LIST all or ci,codeql,security,test,draft-pr,release-pr,release,dependabot
|
|
24
24
|
--package-manager NAME auto, bun, pnpm, yarn, or npm
|
|
25
|
+
--runtime-repository OWNER/REPO Reusable workflow runtime repository
|
|
25
26
|
--release-type NAME auto, node, python, rust, simple, or none
|
|
26
27
|
--license NAME agpl-3.0-or-later, mit, preserve, or none
|
|
27
28
|
--license-file PATH Use an exact custom license file
|
|
@@ -49,6 +50,7 @@ function parseArgs(argv) {
|
|
|
49
50
|
languages: process.env.REPO_FOUNDRY_LANGUAGES || 'auto',
|
|
50
51
|
features: process.env.REPO_FOUNDRY_FEATURES || 'all',
|
|
51
52
|
packageManager: process.env.REPO_FOUNDRY_PACKAGE_MANAGER || 'auto',
|
|
53
|
+
runtimeRepository: process.env.REPO_FOUNDRY_RUNTIME_REPOSITORY || '0xPlayerOne/code-foundry',
|
|
52
54
|
releaseType: process.env.REPO_FOUNDRY_RELEASE_TYPE || 'auto',
|
|
53
55
|
license: process.env.REPO_FOUNDRY_LICENSE || (command === 'init' ? 'agpl-3.0-or-later' : 'preserve'),
|
|
54
56
|
licenseFile: process.env.REPO_FOUNDRY_LICENSE_FILE || '',
|
|
@@ -69,6 +71,7 @@ function parseArgs(argv) {
|
|
|
69
71
|
['--languages', 'languages'],
|
|
70
72
|
['--features', 'features'],
|
|
71
73
|
['--package-manager', 'packageManager'],
|
|
74
|
+
['--runtime-repository', 'runtimeRepository'],
|
|
72
75
|
['--release-type', 'releaseType'],
|
|
73
76
|
['--license', 'license'],
|
|
74
77
|
['--license-file', 'licenseFile'],
|
|
@@ -120,6 +123,7 @@ function main() {
|
|
|
120
123
|
if (options.licenseFile) common.push('--license-file', options.licenseFile)
|
|
121
124
|
if (options.languagesSet) common.push('--languages', options.languages)
|
|
122
125
|
if (options.featuresSet) common.push('--features', options.features)
|
|
126
|
+
common.push('--runtime-repository', options.runtimeRepository)
|
|
123
127
|
if (options.prune) common.push('--prune')
|
|
124
128
|
if (options.force) common.push('--force')
|
|
125
129
|
if (options.dryRun) common.push('--check')
|
|
@@ -133,6 +137,7 @@ function main() {
|
|
|
133
137
|
'--languages', options.languages,
|
|
134
138
|
'--features', options.features,
|
|
135
139
|
'--package-manager', options.packageManager,
|
|
140
|
+
'--runtime-repository', options.runtimeRepository,
|
|
136
141
|
'--release-type', options.releaseType,
|
|
137
142
|
'--license', options.license,
|
|
138
143
|
]
|