@pixpilot/scaffoldfy-configs 0.40.4 → 0.42.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/CHANGELOG.md +13 -0
- package/README.md +10 -0
- package/codeql-private-repo/codeql-analysis.yml +39 -0
- package/codeql-private-repo/scaffoldfy.json +32 -0
- package/package.json +4 -4
- package/test/create-packages.test.ts +101 -0
- package/workspace-initializer/scaffoldfy.json +24 -6
- package/workspace-initializer/scripts/create-packages.cjs +46 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @pixpilot/scaffoldfy-configs
|
|
2
2
|
|
|
3
|
+
## 0.42.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- add `--set <key=value>` option for preset prompt answers
|
|
8
|
+
- 0319f19: workspace-initializer: create multiple packages at once from a comma separated list of names
|
|
9
|
+
|
|
10
|
+
## 0.41.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- add CodeQL workflow for private repositories
|
|
15
|
+
|
|
3
16
|
## 0.40.4
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -14,6 +14,16 @@ This package provides the following scaffoldfy templates:
|
|
|
14
14
|
|
|
15
15
|
<!-- scaffoldfy-templates:start -->
|
|
16
16
|
|
|
17
|
+
### codeql-private-repo
|
|
18
|
+
|
|
19
|
+
Replaces the CodeQL workflow with the pixpilot/codeql-scanner action for private repositories
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npx @pixpilot/scaffoldfy@latest --config https://unpkg.com/@pixpilot/scaffoldfy-configs@latest/codeql-private-repo/scaffoldfy.json
|
|
25
|
+
```
|
|
26
|
+
|
|
17
27
|
### license-file
|
|
18
28
|
|
|
19
29
|
Generate a LICENSE file with common open-source licenses
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: CodeQL Analyser
|
|
2
|
+
|
|
3
|
+
permissions:
|
|
4
|
+
security-events: write
|
|
5
|
+
actions: read
|
|
6
|
+
contents: read
|
|
7
|
+
issues: write # Required for pixpilot/codeql-scanner@main
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
branches:
|
|
12
|
+
- main
|
|
13
|
+
- master
|
|
14
|
+
pull_request:
|
|
15
|
+
branches:
|
|
16
|
+
- main
|
|
17
|
+
- master
|
|
18
|
+
schedule:
|
|
19
|
+
# ┌───────────── minute (0 - 59)
|
|
20
|
+
# │ ┌───────────── hour (0 - 23)
|
|
21
|
+
# │ │ ┌───────────── day of the month (1 - 31)
|
|
22
|
+
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
|
23
|
+
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
|
24
|
+
# │ │ │ │ │
|
|
25
|
+
# * * * * *
|
|
26
|
+
- cron: '30 1 * * 0' # Every Sunday at 01:30 UTC
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
analyze:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout repository
|
|
33
|
+
uses: actions/checkout@v4
|
|
34
|
+
|
|
35
|
+
- name: Run CodeQL Scanner
|
|
36
|
+
uses: pixpilot/codeql-scanner@main
|
|
37
|
+
with:
|
|
38
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
39
|
+
config-file: .github/codeql/codeql-config.yml
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../node_modules/@pixpilot/scaffoldfy/schema/scaffoldfy.schema.json",
|
|
3
|
+
"name": "codeql-private-repo",
|
|
4
|
+
"description": "Replaces the CodeQL workflow with the pixpilot/codeql-scanner action for private repositories",
|
|
5
|
+
"prompts": [
|
|
6
|
+
{
|
|
7
|
+
"id": "isPrivateRepo",
|
|
8
|
+
"type": "confirm",
|
|
9
|
+
"message": "Is this a private repository?",
|
|
10
|
+
"default": {
|
|
11
|
+
"type": "exec",
|
|
12
|
+
"value": "node -e \"try{process.stdout.write(require('child_process').execSync('gh repo view --json isPrivate -q .isPrivate',{stdio:['ignore','pipe','ignore']}).toString().trim())}catch{process.stdout.write('false')}\""
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"tasks": [
|
|
17
|
+
{
|
|
18
|
+
"id": "codeql-private-repo-workflow",
|
|
19
|
+
"name": "Replace CodeQL workflow for private repo",
|
|
20
|
+
"description": "Overwrites the CodeQL workflow to use pixpilot/codeql-scanner",
|
|
21
|
+
"enabled": {
|
|
22
|
+
"type": "condition",
|
|
23
|
+
"value": "isPrivateRepo === true"
|
|
24
|
+
},
|
|
25
|
+
"type": "write",
|
|
26
|
+
"config": {
|
|
27
|
+
"templateFile": "codeql-analysis.yml",
|
|
28
|
+
"file": ".github/workflows/codeql-analysis.yml"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixpilot/scaffoldfy-configs",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.42.0",
|
|
5
5
|
"author": "PixPilot <m.doaie@hotmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "^22.18.11",
|
|
31
31
|
"eslint": "^9.38.0",
|
|
32
|
-
"@internal/
|
|
32
|
+
"@internal/tsdown-config": "0.1.0",
|
|
33
33
|
"@internal/eslint-config": "0.3.0",
|
|
34
|
+
"@internal/vitest-config": "0.1.0",
|
|
34
35
|
"@internal/prettier-config": "0.0.1",
|
|
35
|
-
"@pixpilot/scaffoldfy": "0.
|
|
36
|
-
"@internal/tsdown-config": "0.1.0"
|
|
36
|
+
"@pixpilot/scaffoldfy": "0.56.0"
|
|
37
37
|
},
|
|
38
38
|
"prettier": "@internal/prettier-config",
|
|
39
39
|
"publishConfig": {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
7
|
+
|
|
8
|
+
const SCRIPT_PATH = path.join(
|
|
9
|
+
__dirname,
|
|
10
|
+
'..',
|
|
11
|
+
'workspace-initializer',
|
|
12
|
+
'scripts',
|
|
13
|
+
'create-packages.cjs',
|
|
14
|
+
);
|
|
15
|
+
const temporaryDirectories: string[] = [];
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
for (const directory of temporaryDirectories.splice(0)) {
|
|
19
|
+
fs.rmSync(directory, { force: true, recursive: true });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Put a fake `pnpm` on PATH that appends its arguments to a log file
|
|
25
|
+
*/
|
|
26
|
+
function createFakePnpm(): { binDirectory: string; logPath: string } {
|
|
27
|
+
const testDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'create-packages-'));
|
|
28
|
+
temporaryDirectories.push(testDirectory);
|
|
29
|
+
|
|
30
|
+
const binDirectory = path.join(testDirectory, 'bin');
|
|
31
|
+
const logPath = path.join(testDirectory, 'calls.log');
|
|
32
|
+
const fakePnpmScript = path.join(binDirectory, 'fake-pnpm.cjs');
|
|
33
|
+
fs.mkdirSync(binDirectory, { recursive: true });
|
|
34
|
+
fs.writeFileSync(
|
|
35
|
+
fakePnpmScript,
|
|
36
|
+
`require('node:fs').appendFileSync(${JSON.stringify(logPath)}, process.argv.slice(2).join(' ') + '\\n');`,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (process.platform === 'win32') {
|
|
40
|
+
fs.writeFileSync(
|
|
41
|
+
path.join(binDirectory, 'pnpm.cmd'),
|
|
42
|
+
`@"${process.execPath}" "${fakePnpmScript}" %*\r\n`,
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
const pnpmPath = path.join(binDirectory, 'pnpm');
|
|
46
|
+
fs.writeFileSync(
|
|
47
|
+
pnpmPath,
|
|
48
|
+
`#!/bin/sh\n"${process.execPath}" "${fakePnpmScript}" "$@"\n`,
|
|
49
|
+
);
|
|
50
|
+
fs.chmodSync(pnpmPath, 0o755);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { binDirectory, logPath };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function runScript(packageNames: string, binDirectory: string) {
|
|
57
|
+
const pathKey =
|
|
58
|
+
Object.keys(process.env).find((key) => key.toUpperCase() === 'PATH') ?? 'PATH';
|
|
59
|
+
return spawnSync(process.execPath, [SCRIPT_PATH], {
|
|
60
|
+
encoding: 'utf8',
|
|
61
|
+
env: {
|
|
62
|
+
...process.env,
|
|
63
|
+
[pathKey]: `${binDirectory}${path.delimiter}${process.env[pathKey] ?? ''}`,
|
|
64
|
+
PACKAGE_NAMES: packageNames,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
describe('workspace-initializer create-packages script', () => {
|
|
70
|
+
it('runs the package generator once per comma separated name', () => {
|
|
71
|
+
const { binDirectory, logPath } = createFakePnpm();
|
|
72
|
+
|
|
73
|
+
const result = runScript(' pkg-a, pkg-b ,,@scope/pkg-c ', binDirectory);
|
|
74
|
+
|
|
75
|
+
expect(result.status).toBe(0);
|
|
76
|
+
expect(fs.readFileSync(logPath, 'utf8').trim().split(/\r?\n/u)).toEqual([
|
|
77
|
+
'run gen:package --set packageBaseName=pkg-a',
|
|
78
|
+
'run gen:package --set packageBaseName=pkg-b',
|
|
79
|
+
'run gen:package --set packageBaseName=@scope/pkg-c',
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('skips when no names are given', () => {
|
|
84
|
+
const { binDirectory, logPath } = createFakePnpm();
|
|
85
|
+
|
|
86
|
+
const result = runScript(' , ', binDirectory);
|
|
87
|
+
|
|
88
|
+
expect(result.status).toBe(0);
|
|
89
|
+
expect(fs.existsSync(logPath)).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('rejects names with shell characters', () => {
|
|
93
|
+
const { binDirectory, logPath } = createFakePnpm();
|
|
94
|
+
|
|
95
|
+
const result = runScript('pkg-a, bad;rm -rf', binDirectory);
|
|
96
|
+
|
|
97
|
+
expect(result.status).toBe(1);
|
|
98
|
+
expect(result.stderr).toContain('Invalid package name(s): bad;rm -rf');
|
|
99
|
+
expect(fs.existsSync(logPath)).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"../license-file/scaffoldfy.json",
|
|
8
8
|
"../update-root-package-json/scaffoldfy.json",
|
|
9
9
|
"../security-policy/scaffoldfy.json",
|
|
10
|
+
"../codeql-private-repo/scaffoldfy.json",
|
|
10
11
|
"../monorepo-generate-packages-section/scaffoldfy.json"
|
|
11
12
|
],
|
|
12
13
|
"name": "pnpm-turbo-monorepo-template-setup",
|
|
@@ -21,8 +22,18 @@
|
|
|
21
22
|
{
|
|
22
23
|
"id": "createFirstPackagePrompt",
|
|
23
24
|
"type": "confirm",
|
|
24
|
-
"message": "Create
|
|
25
|
+
"message": "Create packages now?",
|
|
25
26
|
"default": false
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "packageNames",
|
|
30
|
+
"type": "input",
|
|
31
|
+
"message": "Enter package names (comma separated, e.g. my-package, my-other-package)",
|
|
32
|
+
"required": true,
|
|
33
|
+
"enabled": {
|
|
34
|
+
"type": "condition",
|
|
35
|
+
"value": "createFirstPackagePrompt === true"
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
38
|
],
|
|
28
39
|
"tasks": [
|
|
@@ -87,12 +98,19 @@
|
|
|
87
98
|
},
|
|
88
99
|
{
|
|
89
100
|
"id": "create-first-package",
|
|
90
|
-
"name": "Create
|
|
91
|
-
"description": "Generate
|
|
92
|
-
"type": "exec",
|
|
101
|
+
"name": "Create packages",
|
|
102
|
+
"description": "Generate each requested package in the monorepo using the package generator",
|
|
103
|
+
"type": "exec-file",
|
|
104
|
+
"enabled": {
|
|
105
|
+
"type": "condition",
|
|
106
|
+
"value": "createFirstPackagePrompt === true"
|
|
107
|
+
},
|
|
93
108
|
"config": {
|
|
94
|
-
"
|
|
95
|
-
"
|
|
109
|
+
"file": "./scripts/create-packages.cjs",
|
|
110
|
+
"runtime": "node",
|
|
111
|
+
"parameters": {
|
|
112
|
+
"PACKAGE_NAMES": "{{packageNames}}"
|
|
113
|
+
}
|
|
96
114
|
}
|
|
97
115
|
},
|
|
98
116
|
{
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable node/prefer-global/process */
|
|
3
|
+
/**
|
|
4
|
+
* Runs the workspace package generator once per package name, pre-filling
|
|
5
|
+
* the package name prompt so only the remaining prompts are asked.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* PACKAGE_NAMES="pkg-a, pkg-b" node create-packages.cjs
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const { spawnSync } = require('node:child_process');
|
|
14
|
+
|
|
15
|
+
const SAFE_NAME = /^[\w.@/-]+$/u;
|
|
16
|
+
|
|
17
|
+
const names = (process.env.PACKAGE_NAMES || '')
|
|
18
|
+
.split(',')
|
|
19
|
+
.map((name) => name.trim())
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
|
|
22
|
+
if (names.length === 0) {
|
|
23
|
+
console.log('No package names provided, skipping package creation.');
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const invalid = names.filter((name) => !SAFE_NAME.test(name));
|
|
28
|
+
if (invalid.length > 0) {
|
|
29
|
+
console.error(`Invalid package name(s): ${invalid.join(', ')}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const [index, name] of names.entries()) {
|
|
34
|
+
console.log(`\nCreating package ${index + 1}/${names.length}: ${name}\n`);
|
|
35
|
+
|
|
36
|
+
const result = spawnSync(
|
|
37
|
+
'pnpm',
|
|
38
|
+
['run', 'gen:package', '--set', `packageBaseName=${name}`],
|
|
39
|
+
{ stdio: 'inherit', shell: true },
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (result.status !== 0) {
|
|
43
|
+
console.error(`Failed to create package: ${name}`);
|
|
44
|
+
process.exit(result.status ?? 1);
|
|
45
|
+
}
|
|
46
|
+
}
|