code-foundry 0.25.0 → 0.27.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/.githooks/pre-commit +3 -4
- package/.github/CONTRIBUTING.md +10 -13
- package/.github/actions/setup/action.yml +50 -3
- package/.github/code-foundry.yml +6 -1
- package/.github/licenses/AGPL-3.0-or-later.txt +661 -0
- package/.github/licenses/GPL-3.0-or-later.txt +674 -0
- package/.github/licenses/MIT.txt +4 -16
- package/.github/workflows/ci.yml +20 -23
- package/.github/workflows/ci_self-ci.yml +1 -1
- package/.github/workflows/codeql.yml +23 -29
- package/.github/workflows/codeql_self-ci.yml +1 -1
- package/.github/workflows/draft-pr.yml +2 -2
- package/.github/workflows/release-pr.yml +4 -4
- package/.github/workflows/release.yml +17 -29
- package/.github/workflows/security.yml +24 -19
- package/.github/workflows/security_self-ci.yml +1 -1
- package/.github/workflows/test.yml +20 -20
- package/.github/workflows/test_self-ci.yml +1 -1
- package/AGENTS.md +13 -10
- package/CHANGELOG.md +28 -0
- package/README.md +19 -8
- package/docs/CONFIGURATION.md +11 -2
- package/docs/INITIALIZATION.md +9 -5
- package/docs/RELEASES.md +5 -0
- package/docs/WORKFLOWS.md +12 -5
- package/package.json +7 -3
- package/src/cli.mjs +29 -25
- package/src/commands/doctor.mjs +70 -0
- package/src/commands/sync.mjs +224 -0
- package/src/lib/config.mjs +38 -0
- package/src/lib/profile.mjs +114 -0
- package/src/runtime.mjs +316 -0
- package/.github/scripts/bootstrap.sh +0 -21
- package/.github/scripts/changed-files.sh +0 -96
- package/.github/scripts/ci.sh +0 -641
- package/.github/scripts/codeql-languages.sh +0 -91
- package/.github/scripts/doctor.sh +0 -98
- package/.github/scripts/format-fast-path.sh +0 -80
- package/.github/scripts/init-repo.sh +0 -264
- package/.github/scripts/pre-commit.sh +0 -67
- package/.github/scripts/profile.sh +0 -186
- package/.github/scripts/security.sh +0 -214
- package/.github/scripts/sitecustomize.py +0 -17
- package/.github/scripts/sync-codeowners.sh +0 -76
- package/.github/scripts/sync-protection.sh +0 -138
- package/.github/scripts/sync-template.sh +0 -744
- package/.github/scripts/turbo-cache-probe.sh +0 -102
|
@@ -61,15 +61,15 @@ jobs:
|
|
|
61
61
|
path: .code-foundry
|
|
62
62
|
sparse-checkout: |
|
|
63
63
|
.github/actions
|
|
64
|
-
|
|
64
|
+
src/lib
|
|
65
|
+
src/runtime.mjs
|
|
65
66
|
- name: Install runtime
|
|
66
67
|
run: |
|
|
67
|
-
mkdir -p .github/actions
|
|
68
|
+
mkdir -p .github/actions
|
|
68
69
|
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
69
|
-
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
70
70
|
- name: Detect
|
|
71
71
|
id: applicability
|
|
72
|
-
run:
|
|
72
|
+
run: node .code-foundry/src/runtime.mjs ci task_profile unit >> "$GITHUB_OUTPUT"
|
|
73
73
|
- name: Setup
|
|
74
74
|
if: steps.applicability.outputs.applicable == 'true'
|
|
75
75
|
uses: ./.github/actions/setup
|
|
@@ -87,7 +87,7 @@ jobs:
|
|
|
87
87
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
88
88
|
- name: Unit
|
|
89
89
|
if: steps.applicability.outputs.applicable == 'true'
|
|
90
|
-
run:
|
|
90
|
+
run: node .code-foundry/src/runtime.mjs ci unit
|
|
91
91
|
- name: Upload coverage
|
|
92
92
|
if: >-
|
|
93
93
|
always() &&
|
|
@@ -122,15 +122,15 @@ jobs:
|
|
|
122
122
|
path: .code-foundry
|
|
123
123
|
sparse-checkout: |
|
|
124
124
|
.github/actions
|
|
125
|
-
|
|
125
|
+
src/lib
|
|
126
|
+
src/runtime.mjs
|
|
126
127
|
- name: Install runtime
|
|
127
128
|
run: |
|
|
128
|
-
mkdir -p .github/actions
|
|
129
|
+
mkdir -p .github/actions
|
|
129
130
|
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
130
|
-
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
131
131
|
- name: Detect
|
|
132
132
|
id: applicability
|
|
133
|
-
run:
|
|
133
|
+
run: node .code-foundry/src/runtime.mjs ci task_profile integration >> "$GITHUB_OUTPUT"
|
|
134
134
|
- name: Setup
|
|
135
135
|
if: steps.applicability.outputs.applicable == 'true'
|
|
136
136
|
uses: ./.github/actions/setup
|
|
@@ -148,7 +148,7 @@ jobs:
|
|
|
148
148
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
149
149
|
- name: Integration
|
|
150
150
|
if: steps.applicability.outputs.applicable == 'true'
|
|
151
|
-
run:
|
|
151
|
+
run: node .code-foundry/src/runtime.mjs ci integration
|
|
152
152
|
|
|
153
153
|
e2e:
|
|
154
154
|
name: E2E
|
|
@@ -167,15 +167,15 @@ jobs:
|
|
|
167
167
|
path: .code-foundry
|
|
168
168
|
sparse-checkout: |
|
|
169
169
|
.github/actions
|
|
170
|
-
|
|
170
|
+
src/lib
|
|
171
|
+
src/runtime.mjs
|
|
171
172
|
- name: Install runtime
|
|
172
173
|
run: |
|
|
173
|
-
mkdir -p .github/actions
|
|
174
|
+
mkdir -p .github/actions
|
|
174
175
|
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
175
|
-
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
176
176
|
- name: Detect
|
|
177
177
|
id: applicability
|
|
178
|
-
run:
|
|
178
|
+
run: node .code-foundry/src/runtime.mjs ci task_profile e2e >> "$GITHUB_OUTPUT"
|
|
179
179
|
- name: Cache browser binaries
|
|
180
180
|
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.browser == 'true'
|
|
181
181
|
uses: ./.github/actions/cache
|
|
@@ -205,7 +205,7 @@ jobs:
|
|
|
205
205
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
206
206
|
- name: E2E
|
|
207
207
|
if: steps.applicability.outputs.applicable == 'true'
|
|
208
|
-
run:
|
|
208
|
+
run: node .code-foundry/src/runtime.mjs ci e2e
|
|
209
209
|
|
|
210
210
|
smoke:
|
|
211
211
|
name: Smoke
|
|
@@ -224,15 +224,15 @@ jobs:
|
|
|
224
224
|
path: .code-foundry
|
|
225
225
|
sparse-checkout: |
|
|
226
226
|
.github/actions
|
|
227
|
-
|
|
227
|
+
src/lib
|
|
228
|
+
src/runtime.mjs
|
|
228
229
|
- name: Install runtime
|
|
229
230
|
run: |
|
|
230
|
-
mkdir -p .github/actions
|
|
231
|
+
mkdir -p .github/actions
|
|
231
232
|
cp -R .code-foundry/.github/actions/. .github/actions/
|
|
232
|
-
cp -R .code-foundry/.github/scripts/. .github/scripts/
|
|
233
233
|
- name: Detect
|
|
234
234
|
id: applicability
|
|
235
|
-
run:
|
|
235
|
+
run: node .code-foundry/src/runtime.mjs ci task_profile smoke >> "$GITHUB_OUTPUT"
|
|
236
236
|
- name: Setup
|
|
237
237
|
if: steps.applicability.outputs.applicable == 'true'
|
|
238
238
|
uses: ./.github/actions/setup
|
|
@@ -250,4 +250,4 @@ jobs:
|
|
|
250
250
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
251
251
|
- name: Smoke
|
|
252
252
|
if: steps.applicability.outputs.applicable == 'true'
|
|
253
|
-
run:
|
|
253
|
+
run: node .code-foundry/src/runtime.mjs ci smoke
|
package/AGENTS.md
CHANGED
|
@@ -7,7 +7,8 @@ They complement `CONTRIBUTING.md`. More specific instructions in nested `AGENTS.
|
|
|
7
7
|
## Mission
|
|
8
8
|
|
|
9
9
|
- Keep formatting, linting, type checking, builds, tests, and coverage reproducible locally and in CI.
|
|
10
|
-
- Prefer the
|
|
10
|
+
- Prefer the repository's configured toolchain; `toolchain: auto` uses native
|
|
11
|
+
tools unless an existing `.mise.toml` is present.
|
|
11
12
|
- Do not commit secrets, generated credentials, local environment files, or machine-specific paths.
|
|
12
13
|
- Add tests for behavior changes and keep coverage thresholds explicit in the project configuration.
|
|
13
14
|
- Make the smallest complete, well-tested change that solves the requested problem without disturbing unrelated work.
|
|
@@ -72,7 +73,9 @@ For normal feature work, branch from `staging` and target pull requests at `stag
|
|
|
72
73
|
|
|
73
74
|
## Toolchain and dependencies
|
|
74
75
|
|
|
75
|
-
-
|
|
76
|
+
- Follow `toolchain: auto` in `.github/code-foundry.yml`; use native tools by
|
|
77
|
+
default and reuse mise only when the repository already has `.mise.toml`.
|
|
78
|
+
- If `toolchain: mise` is selected, run `mise install` before validation.
|
|
76
79
|
- Use the package manager indicated by the existing lockfile:
|
|
77
80
|
- `bun.lock` or `bun.lockb` → Bun
|
|
78
81
|
- `pnpm-lock.yaml` → pnpm
|
|
@@ -88,14 +91,14 @@ For normal feature work, branch from `staging` and target pull requests at `stag
|
|
|
88
91
|
Use the shared scripts when present. They detect supported tools and skip inapplicable checks:
|
|
89
92
|
|
|
90
93
|
```sh
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
node src/runtime.mjs ci format
|
|
95
|
+
node src/runtime.mjs ci lint
|
|
96
|
+
node src/runtime.mjs ci type_check
|
|
97
|
+
node src/runtime.mjs ci build
|
|
98
|
+
node src/runtime.mjs ci unit
|
|
99
|
+
node src/runtime.mjs ci integration
|
|
100
|
+
node src/runtime.mjs ci e2e
|
|
101
|
+
node src/runtime.mjs ci smoke
|
|
99
102
|
Security and dependency audits run through the GitHub Security workflow.
|
|
100
103
|
```
|
|
101
104
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.27.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.26.0...v0.27.0) (2026-07-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add typed javascript cli checks ([2d9464b](https://github.com/0xPlayerOne/code-foundry/commit/2d9464bcbef8aa51607cdf52a6a60e3fc1bdb054))
|
|
9
|
+
* make mise an optional toolchain ([e62f023](https://github.com/0xPlayerOne/code-foundry/commit/e62f0238f4ddc2d1b0f89e0f2b23bca3679b934e))
|
|
10
|
+
* make paid github security checks opt-in ([bbfe899](https://github.com/0xPlayerOne/code-foundry/commit/bbfe8993d88a8415129ce29bfa5d2181807232ba))
|
|
11
|
+
* skip irrelevant language configuration ([39a0003](https://github.com/0xPlayerOne/code-foundry/commit/39a00037ba92152926e7a89759f3255d86a4f26e))
|
|
12
|
+
* standardize optional github security policies ([2cf6bc3](https://github.com/0xPlayerOne/code-foundry/commit/2cf6bc3af161ed8757a03447aab16f3e7ea310d7))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* include runtime libraries in every workflow job ([ce94cd9](https://github.com/0xPlayerOne/code-foundry/commit/ce94cd96a32eff54048712e1bf4b2d34a868ba2e))
|
|
18
|
+
* include runtime libraries in workflow checkout ([4b2c252](https://github.com/0xPlayerOne/code-foundry/commit/4b2c2527c37c82b498c2b3457df5dd52ef7c694f))
|
|
19
|
+
* migrate stale managed docs during sync ([380bab1](https://github.com/0xPlayerOne/code-foundry/commit/380bab1334c9125f97bf333cc29c796e1a16d57d))
|
|
20
|
+
* preserve authored notice files ([342e666](https://github.com/0xPlayerOne/code-foundry/commit/342e666f4e218e094180f10ecdc5a24b85a27b28))
|
|
21
|
+
* preserve repository notice attribution ([7d43911](https://github.com/0xPlayerOne/code-foundry/commit/7d439117ec89882d8d06895528d94ed717ade471))
|
|
22
|
+
* use pinned bun lockfile format ([0f75faf](https://github.com/0xPlayerOne/code-foundry/commit/0f75faf2c7614cc7055cbb4f26a01b3cf1639f85))
|
|
23
|
+
|
|
24
|
+
## [0.26.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.25.0...v0.26.0) (2026-07-28)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* default new repositories to gplv3 ([e200135](https://github.com/0xPlayerOne/code-foundry/commit/e200135939779693eb73a64aaf3587eccdc36ffc))
|
|
30
|
+
|
|
3
31
|
## [0.25.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.24.1...v0.25.0) (2026-07-28)
|
|
4
32
|
|
|
5
33
|
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ npx code-foundry init
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Initialization is repository-aware. It detects supported languages, package
|
|
22
|
-
manager, profile, release strategy, and
|
|
22
|
+
manager, profile, release strategy, and toolchain preference, then writes the
|
|
23
23
|
resolved choices to `.github/code-foundry.yml`.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
@@ -39,7 +39,7 @@ contract. For normal updates, edit that file and run `npx code-foundry sync`.
|
|
|
39
39
|
and Release.
|
|
40
40
|
- A small `.githooks/pre-commit` launcher with language-aware formatting and
|
|
41
41
|
linting.
|
|
42
|
-
- `.mise.toml
|
|
42
|
+
- An optional `.mise.toml`/`mise.lock`, repository profile configuration, and
|
|
43
43
|
standard GitHub forms and policy files.
|
|
44
44
|
- AGENTS instructions, CODEOWNERS, license/notice files, and reusable release
|
|
45
45
|
configuration.
|
|
@@ -56,10 +56,13 @@ The generated configuration is the one place to control the baseline. See
|
|
|
56
56
|
guide and [Initialization and synchronization](docs/INITIALIZATION.md) for
|
|
57
57
|
the two-command workflow.
|
|
58
58
|
|
|
59
|
-
New repositories default to
|
|
60
|
-
|
|
59
|
+
New repositories default to GPL-3.0-or-later. Existing projects preserve an
|
|
60
|
+
authored license unless a replacement is explicitly selected. Our maintained
|
|
61
|
+
repositories explicitly select AGPL-3.0-or-later. Authored
|
|
61
62
|
documentation, application files, custom workflows, and existing `.mise.toml`
|
|
62
|
-
files are preserved by default.
|
|
63
|
+
files are preserved by default. `toolchain: auto` uses an existing mise setup
|
|
64
|
+
when present and otherwise uses native language tooling; choose `native` or
|
|
65
|
+
`mise` explicitly when a repository needs a fixed policy.
|
|
63
66
|
|
|
64
67
|
## Workflow model
|
|
65
68
|
|
|
@@ -75,13 +78,21 @@ test runner. Rust uses `rustfmt`, Clippy with warnings as errors, and native
|
|
|
75
78
|
Cargo tests. Python uses Ruff, uv/pip-compatible setup, and native Python
|
|
76
79
|
tests. Solidity projects retain their native toolchain and test runner.
|
|
77
80
|
|
|
78
|
-
CodeQL remains separate from CI and Security.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
CodeQL remains separate from CI and Security. With the default `codeql: auto`
|
|
82
|
+
and `dependency_review: auto` policies, public repositories use the free GitHub
|
|
83
|
+
security checks while private repositories skip them unless explicitly opted
|
|
84
|
+
in and supported by GitHub Advanced Security. JavaScript, Python, and Rust
|
|
85
|
+
audits remain available without Advanced Security. Code Foundry does not enable
|
|
86
|
+
GitHub Code Quality or other paid GitHub features.
|
|
81
87
|
|
|
82
88
|
See [Workflow and CI conventions](docs/WORKFLOWS.md) for triggers, required
|
|
83
89
|
checks, runners, coverage, caching, and custom workflow extensions.
|
|
84
90
|
|
|
91
|
+
The default contribution policy uses the `staging-release` workflow with
|
|
92
|
+
rebase merges. Repositories can set `merge_strategy: squash` or
|
|
93
|
+
`merge_strategy: merge` in `.github/code-foundry.yml` when their governance
|
|
94
|
+
requires another merge convention.
|
|
95
|
+
|
|
85
96
|
## Releases and publishing
|
|
86
97
|
|
|
87
98
|
The standard flow promotes `staging` into `main`, lets Release Please open a
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -9,6 +9,10 @@ npx code-foundry init
|
|
|
9
9
|
Initialization detects the repository and writes a fully resolved configuration.
|
|
10
10
|
Edit that file directly, then run `npx code-foundry sync`.
|
|
11
11
|
|
|
12
|
+
The default `toolchain: auto` reuses an existing `.mise.toml`; otherwise it
|
|
13
|
+
selects native setup for the detected languages. Use `toolchain: native` to
|
|
14
|
+
prohibit mise or `toolchain: mise` to require it.
|
|
15
|
+
|
|
12
16
|
## Configuration flow
|
|
13
17
|
|
|
14
18
|
```text
|
|
@@ -17,7 +21,7 @@ repository manifests and source
|
|
|
17
21
|
v
|
|
18
22
|
.github/code-foundry.yml
|
|
19
23
|
|
|
|
20
|
-
+--> mise
|
|
24
|
+
+--> native or mise toolchain setup
|
|
21
25
|
+--> standard workflow callers
|
|
22
26
|
+--> runtime repository and version
|
|
23
27
|
+--> release, license, cache, and coverage policy
|
|
@@ -30,13 +34,18 @@ repository manifests and source
|
|
|
30
34
|
| `profile` | `auto`, `application`, `monorepo`, `minimal` | Repository shape |
|
|
31
35
|
| `languages` | detected list | TypeScript, Rust, Python, Solidity |
|
|
32
36
|
| `package_manager` | `bun`, `pnpm`, `yarn`, `npm`, `none` | JavaScript setup |
|
|
37
|
+
| `toolchain` | `auto`, `native`, `mise` | Environment setup policy; defaults to `auto` |
|
|
33
38
|
| `features` | `all` or a list | Standard workflow callers |
|
|
39
|
+
| `codeql` | `auto`, `true`, `false` | CodeQL policy; public repositories default to enabled, non-public repositories default to disabled |
|
|
40
|
+
| `dependency_review` | `auto`, `true`, `false` | Dependency Review policy; public repositories default to enabled, non-public repositories default to disabled |
|
|
34
41
|
| `prune_standard` | `true` or `false` | Remove disabled standard callers |
|
|
35
42
|
| `runtime_repository` | `OWNER/REPO` | Reusable workflow source |
|
|
36
43
|
| `runtime_ref` | tag or branch | Reusable workflow version |
|
|
37
44
|
| `release_type` | `node`, `python`, `rust`, `simple`, `none` | Release strategy |
|
|
38
45
|
| `npm_publish` | `true` or `false` | Opt into npm publication |
|
|
39
|
-
| `license` |
|
|
46
|
+
| `license` | `gpl-3.0-or-later`, `agpl-3.0-or-later`, `mit`, `preserve`, `none` | License policy; new repositories default to GPLv3 |
|
|
47
|
+
| `git_workflow` | `staging-release` | Branch/release model; the standard model promotes `staging` into `main` |
|
|
48
|
+
| `merge_strategy` | `rebase`, `squash`, `merge` | Preferred merge method for contribution and release PRs; defaults to `rebase` |
|
|
40
49
|
| `runner` fields | GitHub runner names | Per-workflow runner policy |
|
|
41
50
|
|
|
42
51
|
Supported features are `ci`, `codeql`, `security`, `test`, `draft-pr`,
|
package/docs/INITIALIZATION.md
CHANGED
|
@@ -11,7 +11,7 @@ npx code-foundry doctor
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
`init` detects supported languages, package manager, repository profile,
|
|
14
|
-
release strategy,
|
|
14
|
+
release strategy, toolchain preference, and standard features. It writes the resolved
|
|
15
15
|
choices to `.github/code-foundry.yml`, initializes the local environment, and
|
|
16
16
|
renders the standard baseline.
|
|
17
17
|
|
|
@@ -25,6 +25,9 @@ manifests, lockfiles, source extensions, workspace metadata, and existing
|
|
|
25
25
|
project scripts. The generated values are explicit, so later syncs are stable
|
|
26
26
|
until a maintainer changes the file.
|
|
27
27
|
|
|
28
|
+
New repositories receive the GNU GPLv3. Existing repositories with an authored
|
|
29
|
+
`LICENSE` keep that license unless the generated configuration is changed.
|
|
30
|
+
|
|
28
31
|
## Runtime selection
|
|
29
32
|
|
|
30
33
|
Workflow callers use `runtime_repository` and `runtime_ref` from
|
|
@@ -37,7 +40,8 @@ Sync updates standard Code Foundry files only. It preserves application code,
|
|
|
37
40
|
authored documentation, existing `.mise.toml` selections, and custom workflows
|
|
38
41
|
such as deployment, search, Slither, or monitoring workflows.
|
|
39
42
|
|
|
40
|
-
The environment bootstrap
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
The environment bootstrap enables repository hooks and uses mise only when an
|
|
44
|
+
existing `.mise.toml` is present or `toolchain: mise` is selected. Otherwise it
|
|
45
|
+
uses the repository's native tools. Use `npx code-foundry doctor` when local
|
|
46
|
+
setup needs to be checked; the CLI supplies the implementation without adding
|
|
47
|
+
maintenance scripts to the consumer repository.
|
package/docs/RELEASES.md
CHANGED
|
@@ -12,6 +12,11 @@ Keep commits Conventional Commit-shaped (`feat:`, `fix:`, `docs:`, `ci:`,
|
|
|
12
12
|
`chore:`, and so on). Release Please uses them to select patch/minor/major
|
|
13
13
|
versions and generate grouped changelog notes.
|
|
14
14
|
|
|
15
|
+
The default `merge_strategy` is `rebase`, matching the repository's linear
|
|
16
|
+
history policy. Set it to `squash` or `merge` in `.github/code-foundry.yml` when
|
|
17
|
+
that repository intentionally uses a different merge convention. The current
|
|
18
|
+
supported `git_workflow` is `staging-release`.
|
|
19
|
+
|
|
15
20
|
The release workflow opens or updates a versioned PR after changes reach
|
|
16
21
|
`main`. Merging that PR updates the changelog, creates the Git tag and GitHub
|
|
17
22
|
Release, and triggers any configured package publication.
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -46,11 +46,18 @@ ambiguous for mixed-language repositories.
|
|
|
46
46
|
|
|
47
47
|
## Security behavior
|
|
48
48
|
|
|
49
|
-
CodeQL is a separate workflow using GitHub's official actions.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
CodeQL is a separate workflow using GitHub's official actions. The default
|
|
50
|
+
`codeql: auto` policy enables it for public repositories and skips it for
|
|
51
|
+
private repositories unless explicitly enabled and Advanced Security is
|
|
52
|
+
available. Dependency Review follows the same policy through
|
|
53
|
+
`dependency_review: auto`; JavaScript, Python, and Rust audits remain
|
|
54
|
+
available without Advanced Security. If GitHub default setup is enabled,
|
|
55
|
+
disable its generated CodeQL workflow to avoid duplicate analysis.
|
|
56
|
+
|
|
57
|
+
Code Foundry does not enable GitHub Code Quality or any paid GitHub feature.
|
|
58
|
+
The repository's format and lint jobs are ordinary CI checks. Set `codeql:
|
|
59
|
+
false` or `dependency_review: false` when a public repository also needs those
|
|
60
|
+
checks disabled.
|
|
54
61
|
|
|
55
62
|
## Branch protection
|
|
56
63
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -42,12 +42,16 @@
|
|
|
42
42
|
"build": "node --check src/cli.mjs",
|
|
43
43
|
"format:check": "node --check src/cli.mjs",
|
|
44
44
|
"lint": "node --check src/cli.mjs",
|
|
45
|
-
"test": "node --
|
|
46
|
-
"type-check": "
|
|
45
|
+
"test": "node --test",
|
|
46
|
+
"type-check": "tsc --project jsconfig.json",
|
|
47
47
|
"pack:check": "npm pack --dry-run",
|
|
48
48
|
"prepublishOnly": "npm test && npm run pack:check"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^24.0.0",
|
|
55
|
+
"typescript": "^5.8.3"
|
|
52
56
|
}
|
|
53
57
|
}
|
package/src/cli.mjs
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
2
3
|
|
|
3
|
-
import { existsSync } from 'node:fs'
|
|
4
4
|
import { resolve } from 'node:path'
|
|
5
|
-
import { spawnSync } from 'node:child_process'
|
|
6
5
|
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { doctor } from './commands/doctor.mjs'
|
|
7
|
+
import { syncRepository } from './commands/sync.mjs'
|
|
7
8
|
|
|
8
9
|
const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)))
|
|
9
10
|
|
|
11
|
+
/** @typedef {{ target: string, dryRun: boolean, force: boolean }} Options */
|
|
12
|
+
/** @typedef {{ command: string, options: Options }} ParsedArgs */
|
|
13
|
+
|
|
10
14
|
const usage = `code-foundry — initialize and maintain agent-ready repositories
|
|
11
15
|
|
|
12
16
|
Usage:
|
|
@@ -25,13 +29,17 @@ Options:
|
|
|
25
29
|
-h, --help Show this help
|
|
26
30
|
`
|
|
27
31
|
|
|
32
|
+
/** @param {string} message @returns {never} */
|
|
28
33
|
function fail(message) {
|
|
29
34
|
console.error(`code-foundry: ${message}`)
|
|
30
35
|
process.exit(2)
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
/** @param {string[]} argv @returns {ParsedArgs} */
|
|
33
39
|
function parseArgs(argv) {
|
|
34
|
-
const
|
|
40
|
+
const first = argv[0]
|
|
41
|
+
const hasCommand = Boolean(first && !first.startsWith('-'))
|
|
42
|
+
const command = hasCommand ? /** @type {string} */ (argv.shift()) : 'init'
|
|
35
43
|
const options = { target: process.cwd(), dryRun: false, force: false }
|
|
36
44
|
|
|
37
45
|
while (argv.length) {
|
|
@@ -52,34 +60,30 @@ function parseArgs(argv) {
|
|
|
52
60
|
return { command, options }
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
function run(script, args, target) {
|
|
56
|
-
const scriptPath = resolve(packageRoot, '.github/scripts', script)
|
|
57
|
-
if (!existsSync(scriptPath)) fail(`package is missing ${script}`)
|
|
58
|
-
const result = spawnSync('bash', [scriptPath, ...args], {
|
|
59
|
-
cwd: target,
|
|
60
|
-
stdio: 'inherit',
|
|
61
|
-
env: process.env,
|
|
62
|
-
})
|
|
63
|
-
if (result.error) fail(result.error.message)
|
|
64
|
-
if (result.status !== 0) process.exit(result.status ?? 1)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
63
|
function main() {
|
|
68
64
|
const { command, options } = parseArgs(process.argv.slice(2))
|
|
69
65
|
const target = resolve(options.target)
|
|
70
|
-
const common = ['--source', packageRoot, '--ref', 'main']
|
|
71
|
-
if (options.dryRun) common.push('--check')
|
|
72
|
-
else common.push('--apply')
|
|
73
|
-
if (options.force) common.push('--force')
|
|
74
66
|
|
|
75
67
|
if (command === 'init') {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
try {
|
|
69
|
+
syncRepository({ target, source: packageRoot, dryRun: options.dryRun, force: options.force, init: true })
|
|
70
|
+
} catch (error) {
|
|
71
|
+
fail(error instanceof Error ? error.message : String(error))
|
|
72
|
+
}
|
|
73
|
+
} else if (command === 'sync') {
|
|
74
|
+
try {
|
|
75
|
+
syncRepository({ target, source: packageRoot, dryRun: options.dryRun, force: options.force })
|
|
76
|
+
} catch (error) {
|
|
77
|
+
fail(error instanceof Error ? error.message : String(error))
|
|
78
|
+
}
|
|
79
|
+
} else if (command === 'doctor') {
|
|
80
|
+
try {
|
|
81
|
+
doctor(target)
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error(`code-foundry: ${error instanceof Error ? error.message : String(error)}`)
|
|
84
|
+
process.exitCode = 1
|
|
85
|
+
}
|
|
80
86
|
}
|
|
81
|
-
else if (command === 'sync') run('sync-template.sh', common, target)
|
|
82
|
-
else if (command === 'doctor') run('doctor.sh', [], target)
|
|
83
87
|
else fail(`unknown command: ${command}`)
|
|
84
88
|
}
|
|
85
89
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
4
|
+
import { join, resolve } from 'node:path'
|
|
5
|
+
import { spawnSync } from 'node:child_process'
|
|
6
|
+
import { includesValue, readConfig } from '../lib/config.mjs'
|
|
7
|
+
import { resolveProfile } from '../lib/profile.mjs'
|
|
8
|
+
|
|
9
|
+
/** @param {string} root */
|
|
10
|
+
export function doctor(root) {
|
|
11
|
+
const target = resolve(root)
|
|
12
|
+
const config = readConfig(join(target, '.github/code-foundry.yml'))
|
|
13
|
+
const profile = resolveProfile(target)
|
|
14
|
+
let errors = 0
|
|
15
|
+
/** @param {string} message */
|
|
16
|
+
const error = (message) => { console.error(`ERROR: ${message}`); errors += 1 }
|
|
17
|
+
/** @param {string} message */
|
|
18
|
+
const warn = (message) => console.warn(`WARN: ${message}`)
|
|
19
|
+
|
|
20
|
+
const toolchain = config.toolchain ?? 'auto'
|
|
21
|
+
if (!['auto', 'native', 'mise'].includes(toolchain)) error(`unsupported toolchain: ${toolchain}`)
|
|
22
|
+
if (toolchain === 'mise' && !existsSync(join(target, '.mise.toml'))) error('.mise.toml is required when toolchain: mise')
|
|
23
|
+
if (toolchain === 'auto') {
|
|
24
|
+
console.log(existsSync(join(target, '.mise.toml'))
|
|
25
|
+
? 'Toolchain: mise (detected from existing .mise.toml).'
|
|
26
|
+
: 'Toolchain: native (mise not configured).')
|
|
27
|
+
}
|
|
28
|
+
const hooks = git(target, ['config', '--get', 'core.hooksPath'])
|
|
29
|
+
if (hooks !== '.githooks') warn('Git hooks are not enabled; run `npx code-foundry init`')
|
|
30
|
+
|
|
31
|
+
const packageFile = join(target, 'package.json')
|
|
32
|
+
if (existsSync(packageFile)) {
|
|
33
|
+
let packageJson
|
|
34
|
+
try { packageJson = JSON.parse(readFileSync(packageFile, 'utf8')) }
|
|
35
|
+
catch { error('package.json is not valid JSON'); packageJson = {} }
|
|
36
|
+
const lockfiles = ['bun.lock', 'bun.lockb', 'pnpm-lock.yaml', 'yarn.lock', 'package-lock.json'].filter((file) => existsSync(join(target, file)))
|
|
37
|
+
const groups = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies']
|
|
38
|
+
if (!lockfiles.length && groups.some((key) => Object.keys(packageJson[key] ?? {}).length)) error('package.json exists but no supported lockfile was found')
|
|
39
|
+
if (lockfiles.length > 1) error('multiple JavaScript lockfiles found; keep one package manager')
|
|
40
|
+
if (packageJson.packageManager && lockfiles.length) {
|
|
41
|
+
const declared = String(packageJson.packageManager).split('@')[0]
|
|
42
|
+
const actual = lockfiles[0]?.startsWith('bun') ? 'bun' : lockfiles[0]?.split('-')[0].replace('.yaml', '')
|
|
43
|
+
if (actual && declared !== actual) error(`packageManager (${declared}) does not match ${actual} lockfile`)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (profile.languages.split(',').includes('rust') && !commandExists('cargo')) error('Cargo is required for this repository')
|
|
48
|
+
if (profile.languages.split(',').includes('rust')) {
|
|
49
|
+
const metadata = spawnSync('cargo', ['metadata', '--no-deps', '--format-version', '1'], { cwd: target, stdio: 'ignore' })
|
|
50
|
+
if (metadata.status !== 0) error('cargo metadata failed')
|
|
51
|
+
}
|
|
52
|
+
if (profile.languages.split(',').includes('python') && !commandExists('python') && !existsSync(join(target, '.venv/bin/python'))) error('Python is required for this repository')
|
|
53
|
+
|
|
54
|
+
for (const workflow of ['ci', 'codeql', 'security', 'test', 'draft-pr', 'release-pr', 'release']) {
|
|
55
|
+
if (includesValue(config.features ?? 'all', workflow) && !existsSync(join(target, `.github/workflows/${workflow}.yml`))) error(`missing enabled workflow: ${workflow}.yml`)
|
|
56
|
+
}
|
|
57
|
+
console.log('Remote CI, Test, Security, CodeQL, and release runtimes are loaded by reusable workflow wrappers.')
|
|
58
|
+
if (errors) throw new Error(`Repository doctor found ${errors} error(s).`)
|
|
59
|
+
console.log('Repository doctor passed.')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @param {string} root @param {string[]} args */
|
|
63
|
+
function git(root, args) {
|
|
64
|
+
return spawnSync('git', args, { cwd: root, encoding: 'utf8' }).stdout?.trim() ?? ''
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** @param {string} command */
|
|
68
|
+
function commandExists(command) {
|
|
69
|
+
return spawnSync(command, ['--version'], { stdio: 'ignore' }).status === 0
|
|
70
|
+
}
|