code-foundry 1.4.1 → 1.5.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/dependabot.yml +4 -2
- package/.github/workflows/cloudflare-deploy.yml +98 -0
- package/.github/workflows/release.yml +10 -6
- package/.oxlintrc.json +1 -1
- package/AGENTS.md +16 -1
- package/CHANGELOG.md +7 -0
- package/README.md +2 -1
- package/docs/CONFIGURATION.md +12 -1
- package/package.json +1 -1
- package/src/commands/sync.mjs +15 -7
- package/src/runtime.mjs +16 -37
package/.github/dependabot.yml
CHANGED
|
@@ -29,8 +29,10 @@ updates:
|
|
|
29
29
|
applies-to: version-updates
|
|
30
30
|
patterns: ['*']
|
|
31
31
|
ignore:
|
|
32
|
-
# TypeScript 7
|
|
33
|
-
#
|
|
32
|
+
# TypeScript 7 (the native compiler) is supported by the oxlint/oxfmt
|
|
33
|
+
# toolchain; the tsconfig must use NodeNext or bundler resolution since
|
|
34
|
+
# legacy node10 resolution was removed. Held with 5.9 until each
|
|
35
|
+
# repository's tsconfig is verified on 7.
|
|
34
36
|
- dependency-name: 'typescript'
|
|
35
37
|
versions: ['>=7.0.0']
|
|
36
38
|
# Held with TypeScript 5.9 above.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: Code Foundry Cloudflare Deploy
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
mode:
|
|
7
|
+
description: 'Deploy mode: preview (wrangler versions upload) or production (wrangler deploy).'
|
|
8
|
+
required: false
|
|
9
|
+
type: string
|
|
10
|
+
default: preview
|
|
11
|
+
working-directory:
|
|
12
|
+
description: 'Directory containing the wrangler configuration.'
|
|
13
|
+
required: false
|
|
14
|
+
type: string
|
|
15
|
+
default: '.'
|
|
16
|
+
runner:
|
|
17
|
+
required: false
|
|
18
|
+
type: string
|
|
19
|
+
default: ubuntu-latest
|
|
20
|
+
wrangler-version:
|
|
21
|
+
required: false
|
|
22
|
+
type: string
|
|
23
|
+
default: 'latest'
|
|
24
|
+
environment:
|
|
25
|
+
description: 'GitHub deployment environment. Defaults to Preview/Production based on the mode.'
|
|
26
|
+
required: false
|
|
27
|
+
type: string
|
|
28
|
+
default: ''
|
|
29
|
+
secrets:
|
|
30
|
+
CLOUDFLARE_API_TOKEN:
|
|
31
|
+
required: true
|
|
32
|
+
CLOUDFLARE_ACCOUNT_ID:
|
|
33
|
+
required: true
|
|
34
|
+
|
|
35
|
+
permissions:
|
|
36
|
+
contents: read
|
|
37
|
+
deployments: write
|
|
38
|
+
|
|
39
|
+
jobs:
|
|
40
|
+
deploy:
|
|
41
|
+
name: Cloudflare Deploy / ${{ inputs.mode }}
|
|
42
|
+
if: vars.CI_BILLING_PAUSED != 'true'
|
|
43
|
+
runs-on: ${{ inputs.runner }}
|
|
44
|
+
timeout-minutes: 20
|
|
45
|
+
steps:
|
|
46
|
+
- name: Checkout
|
|
47
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
48
|
+
with:
|
|
49
|
+
persist-credentials: false
|
|
50
|
+
|
|
51
|
+
- name: Deploy to Cloudflare
|
|
52
|
+
id: deploy
|
|
53
|
+
working-directory: ${{ inputs.working-directory }}
|
|
54
|
+
env:
|
|
55
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
56
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
57
|
+
WRANGLER_VERSION: ${{ inputs.wrangler-version }}
|
|
58
|
+
MODE: ${{ inputs.mode }}
|
|
59
|
+
run: |
|
|
60
|
+
set -euo pipefail
|
|
61
|
+
npx -y wrangler@"$WRANGLER_VERSION" --version
|
|
62
|
+
if [ "$MODE" = "production" ]; then
|
|
63
|
+
npx -y wrangler@"$WRANGLER_VERSION" deploy 2>&1 | tee deploy-output.txt
|
|
64
|
+
elif [ "$MODE" = "preview" ]; then
|
|
65
|
+
npx -y wrangler@"$WRANGLER_VERSION" versions upload --message "preview ${GITHUB_SHA::7}" 2>&1 | tee deploy-output.txt
|
|
66
|
+
else
|
|
67
|
+
echo "Unsupported mode: $MODE (use preview or production)" >&2
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
# Prefer version preview URLs; fall back to the first workers.dev URL.
|
|
71
|
+
url=$(grep -Eo 'https://[a-zA-Z0-9][a-zA-Z0-9.-]*\.workers\.dev' deploy-output.txt | tail -1 || true)
|
|
72
|
+
echo "url=$url" >> "$GITHUB_OUTPUT"
|
|
73
|
+
|
|
74
|
+
- name: Record GitHub deployment
|
|
75
|
+
env:
|
|
76
|
+
GH_TOKEN: ${{ github.token }}
|
|
77
|
+
MODE: ${{ inputs.mode }}
|
|
78
|
+
ENVIRONMENT_OVERRIDE: ${{ inputs.environment }}
|
|
79
|
+
DEPLOY_URL: ${{ steps.deploy.outputs.url }}
|
|
80
|
+
run: |
|
|
81
|
+
set -euo pipefail
|
|
82
|
+
if [ "$MODE" != "production" ] && [ "$MODE" != "preview" ]; then
|
|
83
|
+
echo "Unsupported mode: $MODE" >&2
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
environment="${ENVIRONMENT_OVERRIDE:-$([ "$MODE" = "production" ] && echo Production || echo Preview)}"
|
|
87
|
+
body=$(jq -n \
|
|
88
|
+
--arg ref "$GITHUB_SHA" \
|
|
89
|
+
--arg environment "$environment" \
|
|
90
|
+
--argjson production "$([ "$MODE" = "production" ] && echo true || echo false)" \
|
|
91
|
+
'{ref: $ref, environment: $environment, auto_merge: false, production_environment: $production, required_contexts: []}')
|
|
92
|
+
deployment=$(gh api "repos/$GITHUB_REPOSITORY/deployments" --input - <<< "$body" --jq .id)
|
|
93
|
+
status_args=(-f state=success -f description="Cloudflare $MODE deploy (${GITHUB_SHA::7})")
|
|
94
|
+
if [ -n "$DEPLOY_URL" ]; then
|
|
95
|
+
status_args+=(-f environment_url="$DEPLOY_URL" -f log_url="$DEPLOY_URL")
|
|
96
|
+
fi
|
|
97
|
+
gh api -X POST "repos/$GITHUB_REPOSITORY/deployments/$deployment/statuses" "${status_args[@]}" --jq .state
|
|
98
|
+
echo "Recorded $environment deployment for ${GITHUB_SHA::7}"
|
|
@@ -89,17 +89,21 @@ jobs:
|
|
|
89
89
|
let releaseType = config.release_type || 'auto'
|
|
90
90
|
let npmPublish = config.npm_publish || 'false'
|
|
91
91
|
// The merge audit topology requires rebase for Release Please version
|
|
92
|
-
// pull requests into main, matching the linear-history ruleset.
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
92
|
+
// pull requests into main, matching the linear-history ruleset. The
|
|
93
|
+
// direct topology may also opt into squash: a single-commit release
|
|
94
|
+
// PR squashes to the identical tree and release-please recommends
|
|
95
|
+
// squash. Release automation never defaults to a merge method: an
|
|
96
|
+
// unset or unsupported release_merge_strategy fails the release job
|
|
97
|
+
// before any pull request is created or merged.
|
|
98
|
+
const gitWorkflow = String(config.git_workflow || 'direct').trim().toLowerCase()
|
|
96
99
|
const releaseMergeStrategy = String(config.release_merge_strategy || '').trim().toLowerCase()
|
|
97
100
|
if (releaseType === 'auto') {
|
|
98
101
|
releaseType = fs.existsSync('package.json') ? 'node' : fs.existsSync('pyproject.toml') ? 'python' : fs.existsSync('Cargo.toml') ? 'rust' : fs.existsSync('version.txt') ? 'simple' : 'none'
|
|
99
102
|
}
|
|
100
103
|
if (!['node', 'python', 'rust', 'simple', 'none'].includes(releaseType)) throw new Error(`Unsupported release_type: ${releaseType}`)
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
const allowedStrategies = gitWorkflow === 'staging-release' ? ['rebase'] : ['rebase', 'squash']
|
|
105
|
+
if (!allowedStrategies.includes(releaseMergeStrategy)) {
|
|
106
|
+
throw new Error(`release_merge_strategy must be "rebase"${gitWorkflow === 'staging-release' ? '' : ' or "squash" (direct topology)'} for automated release merges; got ${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}`)
|
|
103
107
|
}
|
|
104
108
|
if (releaseType === 'none' || !fs.existsSync('package.json')) npmPublish = 'false'
|
|
105
109
|
let legacyReleaseType = ''
|
package/.oxlintrc.json
CHANGED
package/AGENTS.md
CHANGED
|
@@ -77,6 +77,21 @@ This repository uses the `staging-release` workflow: topic branches **squash** i
|
|
|
77
77
|
|
|
78
78
|
Merge only with the repository's canonical method. Never merge with `--admin`, never default or auto-select a merge method, and never use a method the branch ruleset does not allow. When in doubt, prefer the merge button's configured method and verify the ruleset after merging. Check `.github/CONTRIBUTING.md` for the complete flow and merge table.
|
|
79
79
|
|
|
80
|
+
### Branch and commit policy
|
|
81
|
+
|
|
82
|
+
Branch rulesets enforce deletions, force-pushes, required status checks, pull
|
|
83
|
+
requests, conversation resolution, and linear history where the repository's
|
|
84
|
+
plan supports them. Mirror those rules even where the plan cannot enforce
|
|
85
|
+
them:
|
|
86
|
+
|
|
87
|
+
- Branch from the default branch using
|
|
88
|
+
`feat/*`, `fix/*`, `chore/*`, `refactor/*`, `docs/*`, or `test/*` names.
|
|
89
|
+
- Never push directly to protected branches; open a pull request.
|
|
90
|
+
- Use Conventional Commit subjects (`feat:`, `fix:`, `chore:`, …); Release
|
|
91
|
+
Please depends on them to version releases.
|
|
92
|
+
- Keep pull requests focused; merge with the canonical method only after
|
|
93
|
+
required checks pass.
|
|
94
|
+
|
|
80
95
|
## Toolchain and dependencies
|
|
81
96
|
|
|
82
97
|
- Follow `toolchain: auto` in `.github/code-foundry.yml`; use native tools by
|
|
@@ -112,7 +127,7 @@ Run focused tests first, then the complete applicable set for release, security,
|
|
|
112
127
|
|
|
113
128
|
At minimum:
|
|
114
129
|
|
|
115
|
-
- TypeScript/JavaScript: Oxfmt formatting, Oxlint linting, type-check, build, and Bun's native test runner for unit/integration tests; use the project's native browser runner for E2E tests. Repositories
|
|
130
|
+
- TypeScript/JavaScript: Oxfmt formatting, Oxlint linting, type-check, build, and Bun's native test runner for unit/integration tests; use the project's native browser runner for E2E tests. Repositories using a different linter or formatter keep full control through their own `lint`/`format` scripts, which the runtime honors.
|
|
116
131
|
- Do not add Vitest. Preserve specialized native runners such as Matchstick for The Graph and Hardhat for smart contracts.
|
|
117
132
|
- Rust: default rustfmt, Clippy with warnings treated as errors, check, unit/integration tests, and dependency audit
|
|
118
133
|
- Python: Ruff formatting and linting, compile or type checks, pytest, coverage, and dependency audit
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.4.1...v1.5.0) (2026-09-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **release:** squash release merges, Cloudflare deploy workflow, tooling neutrality ([6a847eb](https://github.com/0xPlayerOne/code-foundry/commit/6a847eb0a3f78dbd343b7b189f32543d621b4b8a))
|
|
9
|
+
|
|
3
10
|
## [1.4.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.4.0...v1.4.1) (2026-09-07)
|
|
4
11
|
|
|
5
12
|
|
package/README.md
CHANGED
|
@@ -74,7 +74,8 @@ The standard workflow triggers are:
|
|
|
74
74
|
|
|
75
75
|
Jobs are language-aware and skip irrelevant setup while remaining visible as
|
|
76
76
|
successful required checks. TypeScript uses Oxlint, Oxfmt, and Bun's native
|
|
77
|
-
test runner (
|
|
77
|
+
test runner (repositories using another linter or formatter keep full control
|
|
78
|
+
through their own `lint`/`format` scripts, which the runtime honors).
|
|
78
79
|
Rust uses `rustfmt`, Clippy with warnings as errors, and native
|
|
79
80
|
Cargo tests. Python uses Ruff, uv/pip-compatible setup, and native Python
|
|
80
81
|
tests. Solidity projects retain their native toolchain and test runner.
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -50,7 +50,7 @@ repository manifests and source
|
|
|
50
50
|
| `license` | `gpl-3.0-or-later`, `agpl-3.0-or-later`, `apache-2.0`, `mit`, `preserve`, `none` | License policy; new repositories default to GPLv3 |
|
|
51
51
|
| `git_workflow` | `direct` (default), `staging-release` | Branch/release model; `direct` opens feature branches into `main`, `staging-release` promotes `staging` into `main` |
|
|
52
52
|
| `merge_strategy` | `rebase` | Promotion merge method for `staging` → `main`; only enforced by the `staging-release` topology |
|
|
53
|
-
| `release_merge_strategy` | `rebase`
|
|
53
|
+
| `release_merge_strategy` | `rebase`, `squash` (direct topology only) | Merge method for Release Please version PRs into `main`; release automation fails closed on anything else |
|
|
54
54
|
| `runner` fields | GitHub runner names | Per-workflow runner policy |
|
|
55
55
|
|
|
56
56
|
Supported features are `ci`, `codeql`, `security`, `test`, `draft-pr`,
|
|
@@ -115,3 +115,14 @@ Each scoped shard must contain tracked Rust source. Code Foundry rejects
|
|
|
115
115
|
absolute paths, parent traversal, duplicates, empty scopes, and more than eight
|
|
116
116
|
shards. Do not split a single crate by arbitrary non-Rust directories: use
|
|
117
117
|
`["all"]` when complete, non-overlapping source scopes are not available.
|
|
118
|
+
|
|
119
|
+
## Cloudflare Workers deployments
|
|
120
|
+
|
|
121
|
+
Repositories that deploy to Cloudflare Workers can opt into GitHub-native
|
|
122
|
+
deployments (Preview/Production environments with deployment statuses, like
|
|
123
|
+
Vercel's integration) by adding a small caller for the runtime's reusable
|
|
124
|
+
`cloudflare-deploy.yml` workflow. The workflow runs `wrangler versions upload`
|
|
125
|
+
for pull-request previews and `wrangler deploy` for production, records a
|
|
126
|
+
GitHub deployment plus status with the workers.dev URL, and respects
|
|
127
|
+
`CI_BILLING_PAUSED`. It requires the `CLOUDFLARE_API_TOKEN` and
|
|
128
|
+
`CLOUDFLARE_ACCOUNT_ID` secrets in the consumer repository.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
|
|
5
5
|
"homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
|
|
6
6
|
"bugs": {
|
package/src/commands/sync.mjs
CHANGED
|
@@ -161,10 +161,18 @@ export function syncRepository(options) {
|
|
|
161
161
|
)
|
|
162
162
|
}
|
|
163
163
|
const releaseMergeStrategy = configured(config.release_merge_strategy, '')
|
|
164
|
-
if (includesValue(features, 'release')
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
if (includesValue(features, 'release')) {
|
|
165
|
+
// Staging-release reconciliations depend on rebase promotions and rebase
|
|
166
|
+
// release commits; the direct topology has no reconciliation step, so it
|
|
167
|
+
// may also squash Release Please version PRs (a single-commit release PR
|
|
168
|
+
// squashes to the identical tree, and release-please recommends squash).
|
|
169
|
+
const allowedReleaseStrategies =
|
|
170
|
+
workflow === 'staging-release' ? ['rebase'] : ['rebase', 'squash']
|
|
171
|
+
if (!allowedReleaseStrategies.includes(releaseMergeStrategy)) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
`Unsupported release_merge_strategy: ${releaseMergeStrategy || '(unset)'}; release automation requires rebase (or squash in the direct topology) for Release Please version pull requests and never defaults to merge.`
|
|
174
|
+
)
|
|
175
|
+
}
|
|
168
176
|
}
|
|
169
177
|
const changed = []
|
|
170
178
|
|
|
@@ -643,7 +651,7 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
643
651
|
],
|
|
644
652
|
[
|
|
645
653
|
'This repository uses the `staging-release` workflow: topic branches **squash** into `staging`, a promotion PR **rebases** validated changes into `main` (`merge_strategy: rebase`), and the Release Please version PR **rebases** into `main` (`release_merge_strategy: rebase`). Feature PRs land on `staging` with squash merges; promotion and release PRs land on `main` with rebase merges. Re-align `staging` with `main` after a release when needed.',
|
|
646
|
-
'This repository uses the `direct` workflow: topic branches **squash** directly into `main`, and the Release Please version PR
|
|
654
|
+
'This repository uses the `direct` workflow: topic branches **squash** directly into `main`, and the Release Please version PR lands on `main` with the configured `release_merge_strategy` (rebase by default, or squash when opted in). Feature PRs land on `main` with squash merges. No integration branch exists; all pull requests target `main`.',
|
|
647
655
|
],
|
|
648
656
|
],
|
|
649
657
|
'.github/CONTRIBUTING.md': [
|
|
@@ -661,7 +669,7 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
661
669
|
],
|
|
662
670
|
[
|
|
663
671
|
'The Git workflow is `staging-release`: topic branches **squash** into `staging`, a promotion PR **rebases** validated changes into `main` (`merge_strategy: rebase`), and the Release Please version PR **rebases** into `main` (`release_merge_strategy: rebase`). Release automation never defaults to a merge method and never merges with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on any other merge strategy. Re-align `staging` with `main` after a release when needed.',
|
|
664
|
-
'The Git workflow is `direct`: topic branches **squash** directly into `main`, and the Release Please version PR
|
|
672
|
+
'The Git workflow is `direct`: topic branches **squash** directly into `main`, and the Release Please version PR lands on `main` with the configured `release_merge_strategy` (rebase by default, or squash when opted in). Release automation never defaults to a merge method and never merges with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on any other release merge strategy. Feature branches never touch `staging`; repositories with a preview/staging environment opt into `git_workflow: staging-release` explicitly.',
|
|
665
673
|
],
|
|
666
674
|
[
|
|
667
675
|
'git switch staging\ngit pull --ff-only origin staging',
|
|
@@ -687,7 +695,7 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
687
695
|
],
|
|
688
696
|
[
|
|
689
697
|
'| Change | Target | Merge method | Merge gate |\n| ---------------------------- | --------- | ----------------------------------------------- | --------------------------------------------------------- |\n| Working branch | `staging` | Squash | All applicable required checks pass |\n| `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |\n',
|
|
690
|
-
'| Change | Target | Merge method | Merge gate |\n|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` |
|
|
698
|
+
'| Change | Target | Merge method | Merge gate |\n|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` | Configured `release_merge_strategy` (rebase default, or squash in the direct topology) | Validation gate and release policy pass |',
|
|
691
699
|
],
|
|
692
700
|
['1. Create a focused branch from `staging`.', '1. Create a focused branch from `main`.'],
|
|
693
701
|
],
|
package/src/runtime.mjs
CHANGED
|
@@ -327,34 +327,11 @@ function hasDependencyManifest(ecosystem) {
|
|
|
327
327
|
return false
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
/**
|
|
331
|
-
* Detect repository-owned ESLint setup: an eslint dependency (or script
|
|
332
|
-
* reference), or a tracked flat/legacy config file. Repositories without any
|
|
333
|
-
* of these have nothing for the fallback runner to enforce, so lint skips
|
|
334
|
-
* instead of forcing a network fetch of ESLint in CI.
|
|
335
|
-
* @returns {boolean}
|
|
336
|
-
*/
|
|
337
|
-
function hasEslintSetup() {
|
|
338
|
-
const pkg = readPackage() ?? {}
|
|
339
|
-
const scripts = pkg.scripts ?? {}
|
|
340
|
-
const dependencies = {
|
|
341
|
-
...pkg.dependencies,
|
|
342
|
-
...pkg.devDependencies,
|
|
343
|
-
...pkg.optionalDependencies,
|
|
344
|
-
...pkg.peerDependencies,
|
|
345
|
-
}
|
|
346
|
-
if (dependencies.eslint) return true
|
|
347
|
-
if (Object.values(scripts).some((value) => /\beslint\b/.test(String(value)))) return true
|
|
348
|
-
return repositoryTestFiles().some((file) =>
|
|
349
|
-
/(^|\/)(\.eslintrc[^/]*|eslint\.config\.[^/]*)$/.test(file)
|
|
350
|
-
)
|
|
351
|
-
}
|
|
352
|
-
|
|
353
330
|
/**
|
|
354
331
|
* Detect repository-owned Oxlint setup: an oxlint dependency (or script
|
|
355
332
|
* reference) or a tracked `.oxlintrc.json` / `oxlint.config.*` file. Oxlint
|
|
356
|
-
* is the baseline's preferred JavaScript linter;
|
|
357
|
-
*
|
|
333
|
+
* is the baseline's preferred JavaScript linter; repositories without one
|
|
334
|
+
* fall back to their own `lint` script if defined.
|
|
358
335
|
* @returns {boolean}
|
|
359
336
|
*/
|
|
360
337
|
function hasOxlintSetup() {
|
|
@@ -376,8 +353,8 @@ function hasOxlintSetup() {
|
|
|
376
353
|
/**
|
|
377
354
|
* Detect repository-owned Oxfmt setup: an oxfmt dependency (or script
|
|
378
355
|
* reference) or a tracked `.oxfmtrc.json` / `oxfmt.config.*` file. Oxfmt is
|
|
379
|
-
* the baseline's
|
|
380
|
-
*
|
|
356
|
+
* the baseline's formatter; repositories using a different formatter opt out
|
|
357
|
+
* through their own `format`/`fmt` scripts, which the script fallback honors.
|
|
381
358
|
* @returns {boolean}
|
|
382
359
|
*/
|
|
383
360
|
function hasOxfmtSetup() {
|
|
@@ -415,12 +392,13 @@ function ci(task) {
|
|
|
415
392
|
if (
|
|
416
393
|
!scripted &&
|
|
417
394
|
(hasLanguage('typescript') || hasLanguage('javascript')) &&
|
|
418
|
-
hasRootJavascriptProject()
|
|
395
|
+
hasRootJavascriptProject() &&
|
|
396
|
+
hasOxfmtSetup()
|
|
419
397
|
) {
|
|
420
|
-
// Oxfmt is the
|
|
421
|
-
//
|
|
422
|
-
|
|
423
|
-
|
|
398
|
+
// Oxfmt is the baseline's formatter. Repositories that use a different
|
|
399
|
+
// formatter keep full control through their own `format`/`fmt` scripts,
|
|
400
|
+
// which the runScript fallback above already honors.
|
|
401
|
+
runTool('oxfmt', ['--check', '.'])
|
|
424
402
|
}
|
|
425
403
|
if (hasLanguage('python') && hasRootPythonProject()) runTool('ruff', ['format', '--check', '.'])
|
|
426
404
|
if (hasLanguage('rust') && hasRootRustProject()) run('cargo', ['fmt', '--check'])
|
|
@@ -431,12 +409,13 @@ function ci(task) {
|
|
|
431
409
|
if (
|
|
432
410
|
!scripted &&
|
|
433
411
|
(hasLanguage('typescript') || hasLanguage('javascript')) &&
|
|
434
|
-
hasRootJavascriptProject()
|
|
412
|
+
hasRootJavascriptProject() &&
|
|
413
|
+
hasOxlintSetup()
|
|
435
414
|
) {
|
|
436
|
-
// Oxlint is the
|
|
437
|
-
//
|
|
438
|
-
|
|
439
|
-
|
|
415
|
+
// Oxlint is the baseline's linter. Repositories that use a different
|
|
416
|
+
// linter keep full control through their own `lint` script, which the
|
|
417
|
+
// runScript fallback above already honors.
|
|
418
|
+
runTool('oxlint', [])
|
|
440
419
|
}
|
|
441
420
|
if (hasLanguage('python') && hasRootPythonProject()) runTool('ruff', ['check', '.'])
|
|
442
421
|
if (hasLanguage('rust') && hasRootRustProject())
|