@bleedingdev/modern-js-create 3.2.0-ultramodern.17 → 3.2.0-ultramodern.18
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/dist/index.js +3 -1
- package/package.json +1 -1
- package/template/.github/renovate.json +53 -0
- package/template/.github/workflows/ultramodern-gates.yml.handlebars +26 -4
- package/template/README.md +7 -3
- package/template/scripts/validate-ultramodern.mjs.handlebars +49 -0
- package/template-workspace/.github/renovate.json +29 -0
- package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +52 -0
- package/template-workspace/README.md.handlebars +6 -1
- package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +44 -0
package/dist/index.js
CHANGED
|
@@ -1855,6 +1855,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
1855
1855
|
targetRoot: 'generated-project-root',
|
|
1856
1856
|
allowedPaths: [
|
|
1857
1857
|
'.agents/**',
|
|
1858
|
+
'.github/**',
|
|
1858
1859
|
'.modernjs/**',
|
|
1859
1860
|
'AGENTS.md',
|
|
1860
1861
|
'README.md',
|
|
@@ -1871,7 +1872,6 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
1871
1872
|
],
|
|
1872
1873
|
deniedPaths: [
|
|
1873
1874
|
'.git/**',
|
|
1874
|
-
'.github/**',
|
|
1875
1875
|
'.npmrc',
|
|
1876
1876
|
'.yarnrc',
|
|
1877
1877
|
'.env',
|
|
@@ -1919,6 +1919,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
1919
1919
|
],
|
|
1920
1920
|
postMaterializationValidation: [
|
|
1921
1921
|
'ultramodern-workspace-contract-check',
|
|
1922
|
+
'github-workflow-security-enforced',
|
|
1922
1923
|
'pnpm-11-policy-enforced',
|
|
1923
1924
|
'template-manifest-retained'
|
|
1924
1925
|
],
|
|
@@ -2259,6 +2260,7 @@ function createBuiltinTemplateManifest(version) {
|
|
|
2259
2260
|
postMaterializationValidation: [
|
|
2260
2261
|
'ultramodern-contract-check',
|
|
2261
2262
|
'dependency-install-with-lifecycle-deny',
|
|
2263
|
+
'github-workflow-security-enforced',
|
|
2262
2264
|
'package-source-retained',
|
|
2263
2265
|
'pnpm-11-policy-enforced',
|
|
2264
2266
|
'rstest-smoke-tests',
|
package/package.json
CHANGED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
+
"extends": [
|
|
4
|
+
"config:recommended",
|
|
5
|
+
"helpers:pinGitHubActionDigests"
|
|
6
|
+
],
|
|
7
|
+
"dependencyDashboard": true,
|
|
8
|
+
"minimumReleaseAge": "1 day",
|
|
9
|
+
"prConcurrentLimit": 5,
|
|
10
|
+
"prHourlyLimit": 2,
|
|
11
|
+
"rangeStrategy": "bump",
|
|
12
|
+
"schedule": [
|
|
13
|
+
"before 5am on monday"
|
|
14
|
+
],
|
|
15
|
+
"timezone": "Etc/UTC",
|
|
16
|
+
"packageRules": [
|
|
17
|
+
{
|
|
18
|
+
"matchManagers": [
|
|
19
|
+
"github-actions"
|
|
20
|
+
],
|
|
21
|
+
"groupName": "github-actions",
|
|
22
|
+
"labels": [
|
|
23
|
+
"dependencies",
|
|
24
|
+
"github-actions",
|
|
25
|
+
"security"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"matchManagers": [
|
|
30
|
+
"npm"
|
|
31
|
+
],
|
|
32
|
+
"matchUpdateTypes": [
|
|
33
|
+
"patch",
|
|
34
|
+
"minor"
|
|
35
|
+
],
|
|
36
|
+
"groupName": "npm minor and patch updates",
|
|
37
|
+
"labels": [
|
|
38
|
+
"dependencies",
|
|
39
|
+
"npm"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"matchUpdateTypes": [
|
|
44
|
+
"major"
|
|
45
|
+
],
|
|
46
|
+
"dependencyDashboardApproval": true,
|
|
47
|
+
"labels": [
|
|
48
|
+
"dependencies",
|
|
49
|
+
"major"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
@@ -4,27 +4,49 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
pull_request:
|
|
6
6
|
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
defaults:
|
|
11
|
+
run:
|
|
12
|
+
shell: bash
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ultramodern-gates-${{ github.workflow }}-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
7
18
|
jobs:
|
|
8
19
|
ultramodern-gates:
|
|
9
20
|
runs-on: ubuntu-latest
|
|
21
|
+
timeout-minutes: 20
|
|
10
22
|
steps:
|
|
23
|
+
- name: Harden Runner
|
|
24
|
+
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
|
|
25
|
+
with:
|
|
26
|
+
egress-policy: audit
|
|
27
|
+
|
|
11
28
|
- name: Checkout
|
|
12
|
-
uses: actions/checkout@v4
|
|
29
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
persist-credentials: false
|
|
13
33
|
|
|
14
34
|
- name: Setup pnpm
|
|
15
|
-
uses: pnpm/action-setup@v4
|
|
35
|
+
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
|
|
16
36
|
|
|
17
37
|
- name: Setup Node.js
|
|
18
|
-
uses: actions/setup-node@v4
|
|
38
|
+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
|
19
39
|
with:
|
|
20
40
|
node-version: 20
|
|
21
41
|
cache: pnpm
|
|
22
42
|
|
|
23
43
|
- name: Install Dependencies
|
|
24
|
-
run: pnpm install
|
|
44
|
+
run: pnpm install --frozen-lockfile
|
|
25
45
|
|
|
26
46
|
- name: Validate Ultramodern Contract
|
|
27
47
|
run: pnpm run ultramodern:check
|
|
28
48
|
|
|
29
49
|
- name: Build
|
|
50
|
+
env:
|
|
51
|
+
MODERN_PUBLIC_SITE_URL: http://localhost:8080
|
|
30
52
|
run: pnpm run build
|
package/template/README.md
CHANGED
|
@@ -36,9 +36,13 @@ MODERN_BASELINE_ENABLE_BFF_REQUEST_ID=false
|
|
|
36
36
|
MODERN_BASELINE_ENABLE_TELEMETRY_EXPORTERS=false
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
The generated starter also includes `.github/workflows/ultramodern-gates.yml
|
|
40
|
-
|
|
41
|
-
push and pull request
|
|
39
|
+
The generated starter also includes `.github/workflows/ultramodern-gates.yml`
|
|
40
|
+
and `.github/renovate.json`. The workflow runs `pnpm run ultramodern:check` and
|
|
41
|
+
`pnpm run build` on every push and pull request with read-only permissions,
|
|
42
|
+
commit-pinned actions, frozen installs, and StepSecurity audit-mode runner
|
|
43
|
+
hardening. Renovate is configured for dependency dashboard review, one-day
|
|
44
|
+
release age, grouped updates, action digest pinning, and manual approval for
|
|
45
|
+
major upgrades.
|
|
42
46
|
|
|
43
47
|
## Micro Vertical Workspaces
|
|
44
48
|
|
|
@@ -52,6 +52,7 @@ const requiredDeniedPaths = [
|
|
|
52
52
|
const requiredPostMaterialization = [
|
|
53
53
|
'ultramodern-contract-check',
|
|
54
54
|
'dependency-install-with-lifecycle-deny',
|
|
55
|
+
'github-workflow-security-enforced',
|
|
55
56
|
'package-source-retained',
|
|
56
57
|
'pnpm-11-policy-enforced',
|
|
57
58
|
'rstest-smoke-tests',
|
|
@@ -61,6 +62,7 @@ const requiredPaths = [
|
|
|
61
62
|
{{#unless isSubproject}}
|
|
62
63
|
'AGENTS.md',
|
|
63
64
|
'.agents/skills-lock.json',
|
|
65
|
+
'.github/renovate.json',
|
|
64
66
|
'.github/workflows/ultramodern-gates.yml',
|
|
65
67
|
'oxlint.config.ts',
|
|
66
68
|
'oxfmt.config.ts',
|
|
@@ -90,6 +92,53 @@ if (fs.existsSync(path.resolve(process.cwd(), 'src/routes/page.tsx'))) {
|
|
|
90
92
|
process.exit(1);
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
{{#unless isSubproject}}
|
|
96
|
+
const workflowContent = fs.readFileSync(
|
|
97
|
+
path.resolve(process.cwd(), '.github/workflows/ultramodern-gates.yml'),
|
|
98
|
+
'utf-8',
|
|
99
|
+
);
|
|
100
|
+
const renovateConfig = JSON.parse(
|
|
101
|
+
fs.readFileSync(path.resolve(process.cwd(), '.github/renovate.json'), 'utf-8'),
|
|
102
|
+
);
|
|
103
|
+
for (const requiredSnippet of [
|
|
104
|
+
'permissions:\n contents: read',
|
|
105
|
+
'pull_request:',
|
|
106
|
+
'persist-credentials: false',
|
|
107
|
+
'pnpm install --frozen-lockfile',
|
|
108
|
+
'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
|
|
109
|
+
'timeout-minutes:',
|
|
110
|
+
'egress-policy: audit',
|
|
111
|
+
]) {
|
|
112
|
+
if (!workflowContent.includes(requiredSnippet)) {
|
|
113
|
+
console.error(`Generated workflow must retain ${requiredSnippet.split('\n')[0]}`);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (workflowContent.includes('pull_request_target')) {
|
|
118
|
+
console.error('Generated workflow must not use pull_request_target');
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
for (const match of workflowContent.matchAll(/^\s*uses:\s*([^@\s]+)@([^\s#]+)/gmu)) {
|
|
122
|
+
const [, actionName, actionRef] = match;
|
|
123
|
+
if (!/^[a-f0-9]{40}$/u.test(actionRef)) {
|
|
124
|
+
console.error(`Generated workflow must pin ${actionName}@${actionRef} to a commit SHA`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (
|
|
129
|
+
renovateConfig.dependencyDashboard !== true ||
|
|
130
|
+
renovateConfig.minimumReleaseAge !== '1 day' ||
|
|
131
|
+
!renovateConfig.extends?.includes('helpers:pinGitHubActionDigests') ||
|
|
132
|
+
!renovateConfig.packageRules?.some(
|
|
133
|
+
(rule) =>
|
|
134
|
+
rule.dependencyDashboardApproval === true && rule.matchUpdateTypes?.includes('major'),
|
|
135
|
+
)
|
|
136
|
+
) {
|
|
137
|
+
console.error('Generated Renovate config must retain dashboard, release-age, action pinning, and major-approval policy');
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
{{/unless}}
|
|
141
|
+
|
|
93
142
|
const pageContent = fs.readFileSync(
|
|
94
143
|
path.resolve(process.cwd(), 'src/routes/[lang]/page.tsx'),
|
|
95
144
|
'utf-8',
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
+
"extends": ["config:recommended", "helpers:pinGitHubActionDigests"],
|
|
4
|
+
"dependencyDashboard": true,
|
|
5
|
+
"minimumReleaseAge": "1 day",
|
|
6
|
+
"prConcurrentLimit": 5,
|
|
7
|
+
"prHourlyLimit": 2,
|
|
8
|
+
"rangeStrategy": "bump",
|
|
9
|
+
"schedule": ["before 5am on monday"],
|
|
10
|
+
"timezone": "Etc/UTC",
|
|
11
|
+
"packageRules": [
|
|
12
|
+
{
|
|
13
|
+
"matchManagers": ["github-actions"],
|
|
14
|
+
"groupName": "github-actions",
|
|
15
|
+
"labels": ["dependencies", "github-actions", "security"]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"matchManagers": ["npm"],
|
|
19
|
+
"matchUpdateTypes": ["patch", "minor"],
|
|
20
|
+
"groupName": "npm minor and patch updates",
|
|
21
|
+
"labels": ["dependencies", "npm"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"matchUpdateTypes": ["major"],
|
|
25
|
+
"dependencyDashboardApproval": true,
|
|
26
|
+
"labels": ["dependencies", "major"]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Ultramodern Workspace Gates
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
defaults:
|
|
11
|
+
run:
|
|
12
|
+
shell: bash
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ultramodern-workspace-gates-${{ github.workflow }}-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
ultramodern-workspace-gates:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
timeout-minutes: 30
|
|
22
|
+
steps:
|
|
23
|
+
- name: Harden Runner
|
|
24
|
+
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
|
|
25
|
+
with:
|
|
26
|
+
egress-policy: audit
|
|
27
|
+
|
|
28
|
+
- name: Checkout
|
|
29
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
|
|
34
|
+
- name: Setup pnpm
|
|
35
|
+
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
|
|
36
|
+
|
|
37
|
+
- name: Setup Node.js
|
|
38
|
+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
|
39
|
+
with:
|
|
40
|
+
node-version: 20
|
|
41
|
+
cache: pnpm
|
|
42
|
+
|
|
43
|
+
- name: Install Dependencies
|
|
44
|
+
run: pnpm install --frozen-lockfile
|
|
45
|
+
|
|
46
|
+
- name: Validate Ultramodern Workspace Contract
|
|
47
|
+
run: pnpm run ultramodern:check
|
|
48
|
+
|
|
49
|
+
- name: Build Workspace Apps
|
|
50
|
+
env:
|
|
51
|
+
MODERN_PUBLIC_SITE_URL: http://localhost:8080
|
|
52
|
+
run: pnpm -r --filter "./apps/**" run build
|
|
@@ -19,7 +19,12 @@ Run the scaffold validator before adding business code:
|
|
|
19
19
|
pnpm ultramodern:check
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
The topology and ownership metadata are generated under `topology/`.
|
|
22
|
+
The topology and ownership metadata are generated under `topology/`. The
|
|
23
|
+
workspace also ships `.github/workflows/ultramodern-workspace-gates.yml` and
|
|
24
|
+
`.github/renovate.json` with read-only workflow permissions, commit-pinned
|
|
25
|
+
actions, frozen installs, StepSecurity audit-mode runner hardening, dependency
|
|
26
|
+
dashboard review, one-day release age, grouped updates, and manual approval for
|
|
27
|
+
major upgrades.
|
|
23
28
|
|
|
24
29
|
Package source metadata is generated at
|
|
25
30
|
`.modernjs/ultramodern-package-source.json`. The default strategy keeps
|
|
@@ -41,6 +41,8 @@ const requiredPaths = [
|
|
|
41
41
|
'tsconfig.base.json',
|
|
42
42
|
'oxlint.config.ts',
|
|
43
43
|
'oxfmt.config.ts',
|
|
44
|
+
'.github/renovate.json',
|
|
45
|
+
'.github/workflows/ultramodern-workspace-gates.yml',
|
|
44
46
|
'.agents/skills-lock.json',
|
|
45
47
|
'.agents/rstackjs-agent-skills-LICENSE',
|
|
46
48
|
'.agents/skills/rsbuild-best-practices/SKILL.md',
|
|
@@ -121,6 +123,8 @@ const rootPackage = readJson('package.json');
|
|
|
121
123
|
const packageSource = readJson('.modernjs/ultramodern-package-source.json');
|
|
122
124
|
const skillsLock = readJson('.agents/skills-lock.json');
|
|
123
125
|
const pnpmWorkspace = readText('pnpm-workspace.yaml');
|
|
126
|
+
const workflowContent = readText('.github/workflows/ultramodern-workspace-gates.yml');
|
|
127
|
+
const renovateConfig = readJson('.github/renovate.json');
|
|
124
128
|
const deprecatedTanstackRuntime = '@modern-js/runtime/' + 'tanstack-router';
|
|
125
129
|
const expectedModernSpecifier =
|
|
126
130
|
packageSource.strategy === 'install' ? packageSource.modernPackages?.specifier : 'workspace:*';
|
|
@@ -164,6 +168,42 @@ assert(
|
|
|
164
168
|
!pnpmWorkspace.includes('onlyBuiltDependencies'),
|
|
165
169
|
'pnpm-workspace.yaml must use pnpm 11 allowBuilds instead of onlyBuiltDependencies',
|
|
166
170
|
);
|
|
171
|
+
for (const requiredSnippet of [
|
|
172
|
+
'permissions:\n contents: read',
|
|
173
|
+
'pull_request:',
|
|
174
|
+
'persist-credentials: false',
|
|
175
|
+
'pnpm install --frozen-lockfile',
|
|
176
|
+
'pnpm -r --filter "./apps/**" run build',
|
|
177
|
+
'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
|
|
178
|
+
'timeout-minutes:',
|
|
179
|
+
'egress-policy: audit',
|
|
180
|
+
]) {
|
|
181
|
+
assert(
|
|
182
|
+
workflowContent.includes(requiredSnippet),
|
|
183
|
+
`Generated workspace workflow must retain ${requiredSnippet.split('\n')[0]}`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
assert(
|
|
187
|
+
!workflowContent.includes('pull_request_target'),
|
|
188
|
+
'Generated workspace workflow must not use pull_request_target',
|
|
189
|
+
);
|
|
190
|
+
for (const match of workflowContent.matchAll(/^\s*uses:\s*([^@\s]+)@([^\s#]+)/gmu)) {
|
|
191
|
+
const [, actionName, actionRef] = match;
|
|
192
|
+
assert(
|
|
193
|
+
/^[a-f0-9]{40}$/u.test(actionRef),
|
|
194
|
+
`Generated workspace workflow must pin ${actionName}@${actionRef} to a commit SHA`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
assert(
|
|
198
|
+
renovateConfig.dependencyDashboard === true &&
|
|
199
|
+
renovateConfig.minimumReleaseAge === '1 day' &&
|
|
200
|
+
renovateConfig.extends?.includes('helpers:pinGitHubActionDigests') &&
|
|
201
|
+
renovateConfig.packageRules?.some(
|
|
202
|
+
(rule) =>
|
|
203
|
+
rule.dependencyDashboardApproval === true && rule.matchUpdateTypes?.includes('major'),
|
|
204
|
+
),
|
|
205
|
+
'Generated workspace Renovate config must retain dashboard, release-age, action pinning, and major-approval policy',
|
|
206
|
+
);
|
|
167
207
|
assert(
|
|
168
208
|
rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json',
|
|
169
209
|
'Root must point to the UltraModern package source metadata',
|
|
@@ -506,5 +546,9 @@ assert(
|
|
|
506
546
|
manifest.validation?.postMaterializationValidation?.includes('pnpm-11-policy-enforced'),
|
|
507
547
|
'Template manifest must document pnpm 11 policy validation',
|
|
508
548
|
);
|
|
549
|
+
assert(
|
|
550
|
+
manifest.validation?.postMaterializationValidation?.includes('github-workflow-security-enforced'),
|
|
551
|
+
'Template manifest must document generated workflow security validation',
|
|
552
|
+
);
|
|
509
553
|
|
|
510
554
|
console.log('UltraModern workspace scaffold validated');
|