start-command 0.3.1
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.changeset/isolation-support.md +30 -0
- package/.github/workflows/release.yml +292 -0
- package/.husky/pre-commit +1 -0
- package/.prettierignore +6 -0
- package/.prettierrc +10 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +24 -0
- package/README.md +249 -0
- package/REQUIREMENTS.md +229 -0
- package/bun.lock +453 -0
- package/bunfig.toml +3 -0
- package/eslint.config.mjs +122 -0
- package/experiments/debug-regex.js +49 -0
- package/experiments/isolation-design.md +142 -0
- package/experiments/test-cli.sh +42 -0
- package/experiments/test-substitution.js +143 -0
- package/package.json +63 -0
- package/scripts/changeset-version.mjs +38 -0
- package/scripts/check-file-size.mjs +103 -0
- package/scripts/create-github-release.mjs +93 -0
- package/scripts/create-manual-changeset.mjs +89 -0
- package/scripts/format-github-release.mjs +83 -0
- package/scripts/format-release-notes.mjs +219 -0
- package/scripts/instant-version-bump.mjs +121 -0
- package/scripts/publish-to-npm.mjs +129 -0
- package/scripts/setup-npm.mjs +37 -0
- package/scripts/validate-changeset.mjs +107 -0
- package/scripts/version-and-commit.mjs +237 -0
- package/src/bin/cli.js +670 -0
- package/src/lib/args-parser.js +259 -0
- package/src/lib/isolation.js +419 -0
- package/src/lib/substitution.js +323 -0
- package/src/lib/substitutions.lino +308 -0
- package/test/args-parser.test.js +389 -0
- package/test/isolation.test.js +248 -0
- package/test/substitution.test.js +236 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Publish to npm using OIDC trusted publishing
|
|
5
|
+
* Usage: node scripts/publish-to-npm.mjs [--should-pull]
|
|
6
|
+
* should_pull: Optional flag to pull latest changes before publishing (for release job)
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: Update the PACKAGE_NAME constant below to match your package.json
|
|
9
|
+
*
|
|
10
|
+
* Uses link-foundation libraries:
|
|
11
|
+
* - use-m: Dynamic package loading without package.json dependencies
|
|
12
|
+
* - command-stream: Modern shell command execution with streaming support
|
|
13
|
+
* - lino-arguments: Unified configuration from CLI args, env vars, and .lenv files
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { readFileSync, appendFileSync } from 'fs';
|
|
17
|
+
|
|
18
|
+
// TODO: Update this to match your package name in package.json
|
|
19
|
+
const PACKAGE_NAME = 'start-command';
|
|
20
|
+
|
|
21
|
+
// Load use-m dynamically
|
|
22
|
+
const { use } = eval(
|
|
23
|
+
await (await fetch('https://unpkg.com/use-m/use.js')).text()
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// Import link-foundation libraries
|
|
27
|
+
const { $ } = await use('command-stream');
|
|
28
|
+
const { makeConfig } = await use('lino-arguments');
|
|
29
|
+
|
|
30
|
+
// Parse CLI arguments using lino-arguments
|
|
31
|
+
const config = makeConfig({
|
|
32
|
+
yargs: ({ yargs, getenv }) =>
|
|
33
|
+
yargs.option('should-pull', {
|
|
34
|
+
type: 'boolean',
|
|
35
|
+
default: getenv('SHOULD_PULL', false),
|
|
36
|
+
describe: 'Pull latest changes before publishing',
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const { shouldPull } = config;
|
|
41
|
+
const MAX_RETRIES = 3;
|
|
42
|
+
const RETRY_DELAY = 10000; // 10 seconds
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Sleep for specified milliseconds
|
|
46
|
+
* @param {number} ms
|
|
47
|
+
*/
|
|
48
|
+
function sleep(ms) {
|
|
49
|
+
return new Promise((resolve) => globalThis.setTimeout(resolve, ms));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Append to GitHub Actions output file
|
|
54
|
+
* @param {string} key
|
|
55
|
+
* @param {string} value
|
|
56
|
+
*/
|
|
57
|
+
function setOutput(key, value) {
|
|
58
|
+
const outputFile = process.env.GITHUB_OUTPUT;
|
|
59
|
+
if (outputFile) {
|
|
60
|
+
appendFileSync(outputFile, `${key}=${value}\n`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function main() {
|
|
65
|
+
try {
|
|
66
|
+
if (shouldPull) {
|
|
67
|
+
// Pull the latest changes we just pushed
|
|
68
|
+
await $`git pull origin main`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get current version
|
|
72
|
+
const packageJson = JSON.parse(readFileSync('./package.json', 'utf8'));
|
|
73
|
+
const currentVersion = packageJson.version;
|
|
74
|
+
console.log(`Current version to publish: ${currentVersion}`);
|
|
75
|
+
|
|
76
|
+
// Check if this version is already published on npm
|
|
77
|
+
console.log(
|
|
78
|
+
`Checking if version ${currentVersion} is already published...`
|
|
79
|
+
);
|
|
80
|
+
const checkResult =
|
|
81
|
+
await $`npm view "${PACKAGE_NAME}@${currentVersion}" version`.run({
|
|
82
|
+
capture: true,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// command-stream returns { code: 0 } on success, { code: 1 } on failure (e.g., E404)
|
|
86
|
+
// Exit code 0 means version exists, non-zero means version not found
|
|
87
|
+
if (checkResult.code === 0) {
|
|
88
|
+
console.log(`Version ${currentVersion} is already published to npm`);
|
|
89
|
+
setOutput('published', 'true');
|
|
90
|
+
setOutput('published_version', currentVersion);
|
|
91
|
+
setOutput('already_published', 'true');
|
|
92
|
+
return;
|
|
93
|
+
} else {
|
|
94
|
+
// Version not found on npm (E404), proceed with publish
|
|
95
|
+
console.log(
|
|
96
|
+
`Version ${currentVersion} not found on npm, proceeding with publish...`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Publish to npm using OIDC trusted publishing with retry logic
|
|
101
|
+
for (let i = 1; i <= MAX_RETRIES; i++) {
|
|
102
|
+
console.log(`Publish attempt ${i} of ${MAX_RETRIES}...`);
|
|
103
|
+
try {
|
|
104
|
+
await $`npm run changeset:publish`;
|
|
105
|
+
setOutput('published', 'true');
|
|
106
|
+
setOutput('published_version', currentVersion);
|
|
107
|
+
console.log(
|
|
108
|
+
`\u2705 Published ${PACKAGE_NAME}@${currentVersion} to npm`
|
|
109
|
+
);
|
|
110
|
+
return;
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (i < MAX_RETRIES) {
|
|
113
|
+
console.log(
|
|
114
|
+
`Publish failed: ${error.message}, waiting ${RETRY_DELAY / 1000}s before retry...`
|
|
115
|
+
);
|
|
116
|
+
await sleep(RETRY_DELAY);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
console.error(`\u274C Failed to publish after ${MAX_RETRIES} attempts`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error('Error:', error.message);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
main();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Update npm for OIDC trusted publishing
|
|
5
|
+
* npm trusted publishing requires npm >= 11.5.1
|
|
6
|
+
* Node.js 20.x ships with npm 10.x, so we need to update
|
|
7
|
+
*
|
|
8
|
+
* Uses link-foundation libraries:
|
|
9
|
+
* - use-m: Dynamic package loading without package.json dependencies
|
|
10
|
+
* - command-stream: Modern shell command execution with streaming support
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Load use-m dynamically
|
|
14
|
+
const { use } = eval(
|
|
15
|
+
await (await fetch('https://unpkg.com/use-m/use.js')).text()
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// Import command-stream for shell command execution
|
|
19
|
+
const { $ } = await use('command-stream');
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// Get current npm version
|
|
23
|
+
const currentResult = await $`npm --version`.run({ capture: true });
|
|
24
|
+
const currentVersion = currentResult.stdout.trim();
|
|
25
|
+
console.log(`Current npm version: ${currentVersion}`);
|
|
26
|
+
|
|
27
|
+
// Update npm to latest
|
|
28
|
+
await $`npm install -g npm@latest`;
|
|
29
|
+
|
|
30
|
+
// Get updated npm version
|
|
31
|
+
const updatedResult = await $`npm --version`.run({ capture: true });
|
|
32
|
+
const updatedVersion = updatedResult.stdout.trim();
|
|
33
|
+
console.log(`Updated npm version: ${updatedVersion}`);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('Error updating npm:', error.message);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validate changeset for CI - ensures exactly one valid changeset exists
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: Update the package name below to match your package.json
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readdirSync, readFileSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
|
|
12
|
+
// TODO: Update this to match your package name in package.json
|
|
13
|
+
const PACKAGE_NAME = 'start-command';
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
// Count changeset files (excluding README.md and config.json)
|
|
17
|
+
const changesetDir = '.changeset';
|
|
18
|
+
const changesetFiles = readdirSync(changesetDir).filter(
|
|
19
|
+
(file) => file.endsWith('.md') && file !== 'README.md'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const changesetCount = changesetFiles.length;
|
|
23
|
+
console.log(`Found ${changesetCount} changeset file(s)`);
|
|
24
|
+
|
|
25
|
+
// Ensure exactly one changeset file exists
|
|
26
|
+
if (changesetCount === 0) {
|
|
27
|
+
console.error(
|
|
28
|
+
"::error::No changeset found. Please add a changeset by running 'npm run changeset' and commit the result."
|
|
29
|
+
);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
} else if (changesetCount > 1) {
|
|
32
|
+
console.error(
|
|
33
|
+
`::error::Multiple changesets found (${changesetCount}). Each PR should have exactly ONE changeset.`
|
|
34
|
+
);
|
|
35
|
+
console.error('::error::Found changeset files:');
|
|
36
|
+
changesetFiles.forEach((file) => console.error(` ${file}`));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Get the changeset file
|
|
41
|
+
const changesetFile = join(changesetDir, changesetFiles[0]);
|
|
42
|
+
console.log(`Validating changeset: ${changesetFile}`);
|
|
43
|
+
|
|
44
|
+
// Read the changeset file
|
|
45
|
+
const content = readFileSync(changesetFile, 'utf-8');
|
|
46
|
+
|
|
47
|
+
// Check if changeset has a valid type (major, minor, or patch)
|
|
48
|
+
const versionTypeRegex = new RegExp(
|
|
49
|
+
`^['"]${PACKAGE_NAME}['"]:\\s+(major|minor|patch)`,
|
|
50
|
+
'm'
|
|
51
|
+
);
|
|
52
|
+
if (!versionTypeRegex.test(content)) {
|
|
53
|
+
console.error(
|
|
54
|
+
'::error::Changeset must specify a version type: major, minor, or patch'
|
|
55
|
+
);
|
|
56
|
+
console.error(`::error::Expected format in ${changesetFile}:`);
|
|
57
|
+
console.error('::error::---');
|
|
58
|
+
console.error(`::error::'${PACKAGE_NAME}': patch`);
|
|
59
|
+
console.error('::error::---');
|
|
60
|
+
console.error('::error::');
|
|
61
|
+
console.error('::error::Your description here');
|
|
62
|
+
console.error('\nFile content:');
|
|
63
|
+
console.error(content);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Extract description (everything after the closing ---) and check it's not empty
|
|
68
|
+
const parts = content.split('---');
|
|
69
|
+
if (parts.length < 3) {
|
|
70
|
+
console.error(
|
|
71
|
+
'::error::Changeset must include a description of the changes'
|
|
72
|
+
);
|
|
73
|
+
console.error(
|
|
74
|
+
"::error::The description should appear after the closing '---' in the changeset file"
|
|
75
|
+
);
|
|
76
|
+
console.error(`::error::Current content of ${changesetFile}:`);
|
|
77
|
+
console.error(content);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const description = parts.slice(2).join('---').trim();
|
|
82
|
+
if (!description) {
|
|
83
|
+
console.error(
|
|
84
|
+
'::error::Changeset must include a description of the changes'
|
|
85
|
+
);
|
|
86
|
+
console.error(
|
|
87
|
+
"::error::The description should appear after the closing '---' in the changeset file"
|
|
88
|
+
);
|
|
89
|
+
console.error(`::error::Current content of ${changesetFile}:`);
|
|
90
|
+
console.error(content);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Extract version type
|
|
95
|
+
const versionTypeMatch = content.match(versionTypeRegex);
|
|
96
|
+
const versionType = versionTypeMatch ? versionTypeMatch[1] : 'unknown';
|
|
97
|
+
|
|
98
|
+
console.log('✅ Changeset validation passed');
|
|
99
|
+
console.log(` Type: ${versionType}`);
|
|
100
|
+
console.log(` Description: ${description}`);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error('Error during changeset validation:', error.message);
|
|
103
|
+
if (process.env.DEBUG) {
|
|
104
|
+
console.error('Stack trace:', error.stack);
|
|
105
|
+
}
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Version packages and commit to main
|
|
5
|
+
* Usage: node scripts/version-and-commit.mjs --mode <changeset|instant> [--bump-type <type>] [--description <desc>]
|
|
6
|
+
* changeset: Run changeset version
|
|
7
|
+
* instant: Run instant version bump with bump_type (patch|minor|major) and optional description
|
|
8
|
+
*
|
|
9
|
+
* Uses link-foundation libraries:
|
|
10
|
+
* - use-m: Dynamic package loading without package.json dependencies
|
|
11
|
+
* - command-stream: Modern shell command execution with streaming support
|
|
12
|
+
* - lino-arguments: Unified configuration from CLI args, env vars, and .lenv files
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFileSync, appendFileSync, readdirSync } from 'fs';
|
|
16
|
+
|
|
17
|
+
// Load use-m dynamically
|
|
18
|
+
const { use } = eval(
|
|
19
|
+
await (await fetch('https://unpkg.com/use-m/use.js')).text()
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// Import link-foundation libraries
|
|
23
|
+
const { $ } = await use('command-stream');
|
|
24
|
+
const { makeConfig } = await use('lino-arguments');
|
|
25
|
+
|
|
26
|
+
// Parse CLI arguments using lino-arguments
|
|
27
|
+
const config = makeConfig({
|
|
28
|
+
yargs: ({ yargs, getenv }) =>
|
|
29
|
+
yargs
|
|
30
|
+
.option('mode', {
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: getenv('MODE', 'changeset'),
|
|
33
|
+
describe: 'Version mode: changeset or instant',
|
|
34
|
+
choices: ['changeset', 'instant'],
|
|
35
|
+
})
|
|
36
|
+
.option('bump-type', {
|
|
37
|
+
type: 'string',
|
|
38
|
+
default: getenv('BUMP_TYPE', ''),
|
|
39
|
+
describe: 'Version bump type for instant mode: major, minor, or patch',
|
|
40
|
+
})
|
|
41
|
+
.option('description', {
|
|
42
|
+
type: 'string',
|
|
43
|
+
default: getenv('DESCRIPTION', ''),
|
|
44
|
+
describe: 'Description for instant version bump',
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const { mode, bumpType, description } = config;
|
|
49
|
+
|
|
50
|
+
// Debug: Log parsed configuration
|
|
51
|
+
console.log('Parsed configuration:', {
|
|
52
|
+
mode,
|
|
53
|
+
bumpType,
|
|
54
|
+
description: description || '(none)',
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Detect if positional arguments were used (common mistake)
|
|
58
|
+
const args = process.argv.slice(2);
|
|
59
|
+
if (args.length > 0 && !args[0].startsWith('--')) {
|
|
60
|
+
console.error('Error: Positional arguments detected!');
|
|
61
|
+
console.error('Command line arguments:', args);
|
|
62
|
+
console.error('');
|
|
63
|
+
console.error(
|
|
64
|
+
'This script requires named arguments (--mode, --bump-type, --description).'
|
|
65
|
+
);
|
|
66
|
+
console.error('Usage:');
|
|
67
|
+
console.error(' Changeset mode:');
|
|
68
|
+
console.error(' node scripts/version-and-commit.mjs --mode changeset');
|
|
69
|
+
console.error(' Instant mode:');
|
|
70
|
+
console.error(
|
|
71
|
+
' node scripts/version-and-commit.mjs --mode instant --bump-type <major|minor|patch> [--description <desc>]'
|
|
72
|
+
);
|
|
73
|
+
console.error('');
|
|
74
|
+
console.error('Examples:');
|
|
75
|
+
console.error(
|
|
76
|
+
' node scripts/version-and-commit.mjs --mode instant --bump-type patch --description "Fix bug"'
|
|
77
|
+
);
|
|
78
|
+
console.error(' node scripts/version-and-commit.mjs --mode changeset');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Validation: Ensure mode is set correctly
|
|
83
|
+
if (mode !== 'changeset' && mode !== 'instant') {
|
|
84
|
+
console.error(`Invalid mode: "${mode}". Expected "changeset" or "instant".`);
|
|
85
|
+
console.error('Command line arguments:', process.argv.slice(2));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Validation: Ensure bump type is provided for instant mode
|
|
90
|
+
if (mode === 'instant' && !bumpType) {
|
|
91
|
+
console.error('Error: --bump-type is required for instant mode');
|
|
92
|
+
console.error(
|
|
93
|
+
'Usage: node scripts/version-and-commit.mjs --mode instant --bump-type <major|minor|patch> [--description <desc>]'
|
|
94
|
+
);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Append to GitHub Actions output file
|
|
100
|
+
* @param {string} key
|
|
101
|
+
* @param {string} value
|
|
102
|
+
*/
|
|
103
|
+
function setOutput(key, value) {
|
|
104
|
+
const outputFile = process.env.GITHUB_OUTPUT;
|
|
105
|
+
if (outputFile) {
|
|
106
|
+
appendFileSync(outputFile, `${key}=${value}\n`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Count changeset files (excluding README.md)
|
|
112
|
+
*/
|
|
113
|
+
function countChangesets() {
|
|
114
|
+
try {
|
|
115
|
+
const changesetDir = '.changeset';
|
|
116
|
+
const files = readdirSync(changesetDir);
|
|
117
|
+
return files.filter((f) => f.endsWith('.md') && f !== 'README.md').length;
|
|
118
|
+
} catch {
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get package version
|
|
125
|
+
* @param {string} source - 'local' or 'remote'
|
|
126
|
+
*/
|
|
127
|
+
async function getVersion(source = 'local') {
|
|
128
|
+
if (source === 'remote') {
|
|
129
|
+
const result = await $`git show origin/main:package.json`.run({
|
|
130
|
+
capture: true,
|
|
131
|
+
});
|
|
132
|
+
return JSON.parse(result.stdout).version;
|
|
133
|
+
}
|
|
134
|
+
return JSON.parse(readFileSync('./package.json', 'utf8')).version;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function main() {
|
|
138
|
+
try {
|
|
139
|
+
// Configure git
|
|
140
|
+
await $`git config user.name "github-actions[bot]"`;
|
|
141
|
+
await $`git config user.email "github-actions[bot]@users.noreply.github.com"`;
|
|
142
|
+
|
|
143
|
+
// Check if remote main has advanced (handles re-runs after partial success)
|
|
144
|
+
console.log('Checking for remote changes...');
|
|
145
|
+
await $`git fetch origin main`;
|
|
146
|
+
|
|
147
|
+
const localHeadResult = await $`git rev-parse HEAD`.run({ capture: true });
|
|
148
|
+
const localHead = localHeadResult.stdout.trim();
|
|
149
|
+
|
|
150
|
+
const remoteHeadResult = await $`git rev-parse origin/main`.run({
|
|
151
|
+
capture: true,
|
|
152
|
+
});
|
|
153
|
+
const remoteHead = remoteHeadResult.stdout.trim();
|
|
154
|
+
|
|
155
|
+
if (localHead !== remoteHead) {
|
|
156
|
+
console.log(
|
|
157
|
+
`Remote main has advanced (local: ${localHead}, remote: ${remoteHead})`
|
|
158
|
+
);
|
|
159
|
+
console.log('This may indicate a previous attempt partially succeeded.');
|
|
160
|
+
|
|
161
|
+
// Check if the remote version is already the expected bump
|
|
162
|
+
const remoteVersion = await getVersion('remote');
|
|
163
|
+
console.log(`Remote version: ${remoteVersion}`);
|
|
164
|
+
|
|
165
|
+
// Check if there are changesets to process
|
|
166
|
+
const changesetCount = countChangesets();
|
|
167
|
+
|
|
168
|
+
if (changesetCount === 0) {
|
|
169
|
+
console.log('No changesets to process and remote has advanced.');
|
|
170
|
+
console.log(
|
|
171
|
+
'Assuming version bump was already completed in a previous attempt.'
|
|
172
|
+
);
|
|
173
|
+
setOutput('version_committed', 'false');
|
|
174
|
+
setOutput('already_released', 'true');
|
|
175
|
+
setOutput('new_version', remoteVersion);
|
|
176
|
+
return;
|
|
177
|
+
} else {
|
|
178
|
+
console.log('Rebasing on remote main to incorporate changes...');
|
|
179
|
+
await $`git rebase origin/main`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Get current version before bump
|
|
184
|
+
const oldVersion = await getVersion();
|
|
185
|
+
console.log(`Current version: ${oldVersion}`);
|
|
186
|
+
|
|
187
|
+
if (mode === 'instant') {
|
|
188
|
+
console.log('Running instant version bump...');
|
|
189
|
+
// Run instant version bump script
|
|
190
|
+
// Rely on command-stream's auto-quoting for proper argument handling
|
|
191
|
+
if (description) {
|
|
192
|
+
await $`node scripts/instant-version-bump.mjs --bump-type ${bumpType} --description ${description}`;
|
|
193
|
+
} else {
|
|
194
|
+
await $`node scripts/instant-version-bump.mjs --bump-type ${bumpType}`;
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
console.log('Running changeset version...');
|
|
198
|
+
// Run changeset version to bump versions and update CHANGELOG
|
|
199
|
+
await $`npm run changeset:version`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Get new version after bump
|
|
203
|
+
const newVersion = await getVersion();
|
|
204
|
+
console.log(`New version: ${newVersion}`);
|
|
205
|
+
setOutput('new_version', newVersion);
|
|
206
|
+
|
|
207
|
+
// Check if there are changes to commit
|
|
208
|
+
const statusResult = await $`git status --porcelain`.run({ capture: true });
|
|
209
|
+
const status = statusResult.stdout.trim();
|
|
210
|
+
|
|
211
|
+
if (status) {
|
|
212
|
+
console.log('Changes detected, committing...');
|
|
213
|
+
|
|
214
|
+
// Stage all changes (package.json, package-lock.json, CHANGELOG.md, deleted changesets)
|
|
215
|
+
await $`git add -A`;
|
|
216
|
+
|
|
217
|
+
// Commit with version number as message
|
|
218
|
+
const commitMessage = newVersion;
|
|
219
|
+
const escapedMessage = commitMessage.replace(/"/g, '\\"');
|
|
220
|
+
await $`git commit -m "${escapedMessage}"`;
|
|
221
|
+
|
|
222
|
+
// Push directly to main
|
|
223
|
+
await $`git push origin main`;
|
|
224
|
+
|
|
225
|
+
console.log('\u2705 Version bump committed and pushed to main');
|
|
226
|
+
setOutput('version_committed', 'true');
|
|
227
|
+
} else {
|
|
228
|
+
console.log('No changes to commit');
|
|
229
|
+
setOutput('version_committed', 'false');
|
|
230
|
+
}
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.error('Error:', error.message);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
main();
|