orch-code 0.1.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +624 -0
  4. package/cmd/apply.go +111 -0
  5. package/cmd/auth.go +393 -0
  6. package/cmd/auth_test.go +100 -0
  7. package/cmd/diff.go +57 -0
  8. package/cmd/doctor.go +149 -0
  9. package/cmd/explain.go +192 -0
  10. package/cmd/explain_test.go +62 -0
  11. package/cmd/init.go +100 -0
  12. package/cmd/interactive.go +1372 -0
  13. package/cmd/interactive_input.go +45 -0
  14. package/cmd/interactive_input_test.go +55 -0
  15. package/cmd/logs.go +72 -0
  16. package/cmd/model.go +84 -0
  17. package/cmd/plan.go +149 -0
  18. package/cmd/provider.go +189 -0
  19. package/cmd/provider_model_doctor_test.go +91 -0
  20. package/cmd/root.go +67 -0
  21. package/cmd/run.go +123 -0
  22. package/cmd/run_engine.go +208 -0
  23. package/cmd/run_engine_test.go +30 -0
  24. package/cmd/session.go +589 -0
  25. package/cmd/session_helpers.go +54 -0
  26. package/cmd/session_integration_test.go +30 -0
  27. package/cmd/session_list_current_test.go +87 -0
  28. package/cmd/session_messages_test.go +163 -0
  29. package/cmd/session_runs_test.go +68 -0
  30. package/cmd/sprint1_integration_test.go +119 -0
  31. package/cmd/stats.go +173 -0
  32. package/cmd/stats_test.go +71 -0
  33. package/cmd/version.go +4 -0
  34. package/go.mod +45 -0
  35. package/go.sum +108 -0
  36. package/internal/agents/agent.go +31 -0
  37. package/internal/agents/coder.go +167 -0
  38. package/internal/agents/planner.go +155 -0
  39. package/internal/agents/reviewer.go +118 -0
  40. package/internal/agents/runtime.go +25 -0
  41. package/internal/agents/runtime_test.go +77 -0
  42. package/internal/auth/account.go +78 -0
  43. package/internal/auth/oauth.go +523 -0
  44. package/internal/auth/store.go +287 -0
  45. package/internal/confidence/policy.go +174 -0
  46. package/internal/confidence/policy_test.go +71 -0
  47. package/internal/confidence/scorer.go +253 -0
  48. package/internal/confidence/scorer_test.go +83 -0
  49. package/internal/config/config.go +331 -0
  50. package/internal/config/config_defaults_test.go +138 -0
  51. package/internal/execution/contract_builder.go +160 -0
  52. package/internal/execution/contract_builder_test.go +68 -0
  53. package/internal/execution/plan_compliance.go +161 -0
  54. package/internal/execution/plan_compliance_test.go +71 -0
  55. package/internal/execution/retry_directive.go +132 -0
  56. package/internal/execution/scope_guard.go +69 -0
  57. package/internal/logger/logger.go +120 -0
  58. package/internal/models/contracts_test.go +100 -0
  59. package/internal/models/models.go +269 -0
  60. package/internal/orchestrator/orchestrator.go +701 -0
  61. package/internal/orchestrator/orchestrator_retry_test.go +135 -0
  62. package/internal/orchestrator/review_engine_test.go +50 -0
  63. package/internal/orchestrator/state.go +42 -0
  64. package/internal/orchestrator/test_classifier_test.go +68 -0
  65. package/internal/patch/applier.go +131 -0
  66. package/internal/patch/applier_test.go +25 -0
  67. package/internal/patch/parser.go +89 -0
  68. package/internal/patch/patch.go +60 -0
  69. package/internal/patch/summary.go +30 -0
  70. package/internal/patch/validator.go +104 -0
  71. package/internal/planning/normalizer.go +416 -0
  72. package/internal/planning/normalizer_test.go +64 -0
  73. package/internal/providers/errors.go +35 -0
  74. package/internal/providers/openai/client.go +498 -0
  75. package/internal/providers/openai/client_test.go +187 -0
  76. package/internal/providers/provider.go +47 -0
  77. package/internal/providers/registry.go +32 -0
  78. package/internal/providers/registry_test.go +57 -0
  79. package/internal/providers/router.go +52 -0
  80. package/internal/providers/state.go +114 -0
  81. package/internal/providers/state_test.go +64 -0
  82. package/internal/repo/analyzer.go +188 -0
  83. package/internal/repo/context.go +83 -0
  84. package/internal/review/engine.go +267 -0
  85. package/internal/review/engine_test.go +103 -0
  86. package/internal/runstore/store.go +137 -0
  87. package/internal/runstore/store_test.go +59 -0
  88. package/internal/runtime/lock.go +150 -0
  89. package/internal/runtime/lock_test.go +57 -0
  90. package/internal/session/compaction.go +260 -0
  91. package/internal/session/compaction_test.go +36 -0
  92. package/internal/session/service.go +117 -0
  93. package/internal/session/service_test.go +113 -0
  94. package/internal/storage/storage.go +1498 -0
  95. package/internal/storage/storage_test.go +413 -0
  96. package/internal/testing/classifier.go +80 -0
  97. package/internal/testing/classifier_test.go +36 -0
  98. package/internal/tools/command.go +160 -0
  99. package/internal/tools/command_test.go +56 -0
  100. package/internal/tools/file.go +111 -0
  101. package/internal/tools/git.go +77 -0
  102. package/internal/tools/invalid_params_test.go +36 -0
  103. package/internal/tools/policy.go +98 -0
  104. package/internal/tools/policy_test.go +36 -0
  105. package/internal/tools/registry_test.go +52 -0
  106. package/internal/tools/result.go +30 -0
  107. package/internal/tools/search.go +86 -0
  108. package/internal/tools/tool.go +94 -0
  109. package/main.go +9 -0
  110. package/npm/orch.js +25 -0
  111. package/package.json +41 -0
  112. package/scripts/changelog.js +20 -0
  113. package/scripts/check-release-version.js +21 -0
  114. package/scripts/lib/release-utils.js +223 -0
  115. package/scripts/postinstall.js +157 -0
  116. package/scripts/release.js +52 -0
package/npm/orch.js ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { spawnSync } = require('node:child_process');
6
+
7
+ const packageRoot = path.resolve(__dirname, '..');
8
+ const binaryName = process.platform === 'win32' ? 'orch.exe' : 'orch';
9
+ const installedBinary = path.join(packageRoot, '.npm-bin', binaryName);
10
+
11
+ if (!fs.existsSync(installedBinary)) {
12
+ console.error('orch binary is not installed. Re-run `npm install -g orch` or install from a published release.');
13
+ process.exit(1);
14
+ }
15
+
16
+ const result = spawnSync(installedBinary, process.argv.slice(2), {
17
+ stdio: 'inherit',
18
+ });
19
+
20
+ if (result.error) {
21
+ console.error(`failed to launch orch: ${result.error.message}`);
22
+ process.exit(1);
23
+ }
24
+
25
+ process.exit(result.status ?? 1);
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "orch-code",
3
+ "version": "0.1.1",
4
+ "description": "Local-first control plane for deterministic AI coding",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "orch": "npm/orch.js"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "node scripts/postinstall.js",
11
+ "pack:dry": "npm pack --dry-run",
12
+ "changelog": "node scripts/changelog.js",
13
+ "release:prepare": "node scripts/release.js",
14
+ "release:patch": "node scripts/release.js patch",
15
+ "release:minor": "node scripts/release.js minor",
16
+ "release:major": "node scripts/release.js major"
17
+ },
18
+ "files": [
19
+ "cmd",
20
+ "internal",
21
+ "npm",
22
+ "scripts",
23
+ "CHANGELOG.md",
24
+ "main.go",
25
+ "go.mod",
26
+ "go.sum",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/furkanbeydemir/orch.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/furkanbeydemir/orch/issues"
36
+ },
37
+ "homepage": "https://github.com/furkanbeydemir/orch#readme",
38
+ "engines": {
39
+ "node": ">=18"
40
+ }
41
+ }
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { bumpVersion, fail, getPackageVersion, isValidSemver, paths, updateChangelog } = require('./lib/release-utils');
4
+
5
+ const requestedVersion = (process.argv[2] || '').trim();
6
+ if (!requestedVersion) {
7
+ fail('missing version argument. Example: npm run changelog -- 0.1.1 or npm run changelog -- patch');
8
+ }
9
+
10
+ const currentVersion = getPackageVersion();
11
+ const nextVersion = ['patch', 'minor', 'major'].includes(requestedVersion)
12
+ ? bumpVersion(currentVersion, requestedVersion)
13
+ : requestedVersion;
14
+
15
+ if (!isValidSemver(nextVersion)) {
16
+ fail(`invalid version: ${nextVersion}`);
17
+ }
18
+
19
+ updateChangelog(nextVersion);
20
+ console.log(`[orch] updated ${paths.changelog} for v${nextVersion}`);
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { fail, getCmdVersion, getPackageVersion } = require('./lib/release-utils');
4
+
5
+ const tag = (process.argv[2] || '').trim();
6
+ if (!tag) {
7
+ fail('missing tag argument, expected something like v0.1.0');
8
+ }
9
+
10
+ const normalizedTag = tag.startsWith('v') ? tag.slice(1) : tag;
11
+ const packageVersion = getPackageVersion();
12
+ if (normalizedTag !== packageVersion) {
13
+ fail(`git tag ${tag} does not match package.json version ${packageVersion}`);
14
+ }
15
+
16
+ const cmdVersion = getCmdVersion();
17
+ if (cmdVersion !== packageVersion) {
18
+ fail(`cmd/version.go version ${cmdVersion} does not match package.json version ${packageVersion}`);
19
+ }
20
+
21
+ console.log(`[orch] release version ${packageVersion} matches tag ${tag}`);
@@ -0,0 +1,223 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+ const { spawnSync } = require('node:child_process');
4
+
5
+ const packageRoot = path.resolve(__dirname, '..', '..');
6
+ const paths = {
7
+ packageJson: path.join(packageRoot, 'package.json'),
8
+ packageLock: path.join(packageRoot, 'package-lock.json'),
9
+ cmdVersion: path.join(packageRoot, 'cmd', 'version.go'),
10
+ changelog: path.join(packageRoot, 'CHANGELOG.md'),
11
+ };
12
+
13
+ function fail(message) {
14
+ console.error(`[orch] ${message}`);
15
+ process.exit(1);
16
+ }
17
+
18
+ function isValidSemver(value) {
19
+ return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(value);
20
+ }
21
+
22
+ function parseSemver(value) {
23
+ if (!isValidSemver(value)) {
24
+ fail(`invalid version: ${value}`);
25
+ }
26
+ const match = value.match(/^(\d+)\.(\d+)\.(\d+)(.*)$/);
27
+ return {
28
+ major: Number(match[1]),
29
+ minor: Number(match[2]),
30
+ patch: Number(match[3]),
31
+ suffix: match[4] || '',
32
+ };
33
+ }
34
+
35
+ function bumpVersion(currentVersion, releaseType) {
36
+ const parsed = parseSemver(currentVersion);
37
+ if (releaseType === 'patch') {
38
+ return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`;
39
+ }
40
+ if (releaseType === 'minor') {
41
+ return `${parsed.major}.${parsed.minor + 1}.0`;
42
+ }
43
+ if (releaseType === 'major') {
44
+ return `${parsed.major + 1}.0.0`;
45
+ }
46
+ return releaseType;
47
+ }
48
+
49
+ function readJSON(filePath) {
50
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
51
+ }
52
+
53
+ function writeJSON(filePath, data) {
54
+ fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`);
55
+ }
56
+
57
+ function getPackageVersion() {
58
+ return readJSON(paths.packageJson).version;
59
+ }
60
+
61
+ function getCmdVersion() {
62
+ const source = fs.readFileSync(paths.cmdVersion, 'utf8');
63
+ const versionMatch = source.match(/version\s*=\s*"([^"]+)"/);
64
+ if (!versionMatch) {
65
+ fail('could not parse cmd/version.go');
66
+ }
67
+ return versionMatch[1];
68
+ }
69
+
70
+ function updateVersions(nextVersion) {
71
+ const pkg = readJSON(paths.packageJson);
72
+ const lock = readJSON(paths.packageLock);
73
+ const currentVersion = pkg.version;
74
+
75
+ pkg.version = nextVersion;
76
+ lock.version = nextVersion;
77
+ if (lock.packages && lock.packages['']) {
78
+ lock.packages[''].version = nextVersion;
79
+ }
80
+
81
+ writeJSON(paths.packageJson, pkg);
82
+ writeJSON(paths.packageLock, lock);
83
+ updateCmdVersion(nextVersion);
84
+ return currentVersion;
85
+ }
86
+
87
+ function updateCmdVersion(nextVersion) {
88
+ const source = fs.readFileSync(paths.cmdVersion, 'utf8');
89
+ if (source.includes(`var version = "${nextVersion}"`)) {
90
+ return;
91
+ }
92
+ const updated = source.replace(/var version = "[^"]+"/, `var version = "${nextVersion}"`);
93
+ if (updated === source) {
94
+ fail('could not update cmd/version.go');
95
+ }
96
+ fs.writeFileSync(paths.cmdVersion, updated);
97
+ }
98
+
99
+ function runGit(args, options = {}) {
100
+ const result = spawnSync('git', args, {
101
+ cwd: packageRoot,
102
+ encoding: 'utf8',
103
+ ...options,
104
+ });
105
+
106
+ if (!options.allowFailure && (result.error || result.status !== 0)) {
107
+ const stderr = (result.stderr || '').trim();
108
+ fail(stderr || `git ${args.join(' ')} failed`);
109
+ }
110
+
111
+ return result;
112
+ }
113
+
114
+ function getLastTag() {
115
+ const result = runGit(['describe', '--tags', '--abbrev=0'], { allowFailure: true });
116
+ if (result.error || result.status !== 0) {
117
+ return '';
118
+ }
119
+ return (result.stdout || '').trim();
120
+ }
121
+
122
+ function getCommitSubjects(range) {
123
+ const args = ['log', '--pretty=format:%s'];
124
+ if (range) {
125
+ args.push(range);
126
+ }
127
+ const result = runGit(args);
128
+ return (result.stdout || '')
129
+ .split('\n')
130
+ .map((line) => line.trim())
131
+ .filter(Boolean);
132
+ }
133
+
134
+ function getWorkingTreeChanges() {
135
+ const result = runGit(['status', '--short']);
136
+ return (result.stdout || '')
137
+ .split('\n')
138
+ .map((line) => line.trim())
139
+ .filter(Boolean);
140
+ }
141
+
142
+ function createTag(version, allowedFiles = []) {
143
+ const tagName = `v${version}`;
144
+ const changes = getWorkingTreeChanges().filter((line) => {
145
+ return !allowedFiles.some((allowedFile) => line.endsWith(allowedFile));
146
+ });
147
+
148
+ if (changes.length > 0) {
149
+ fail('refusing to create tag with unrelated working tree changes present');
150
+ }
151
+
152
+ const tagResult = runGit(['tag', tagName], { stdio: 'inherit', allowFailure: true });
153
+ if (tagResult.error) {
154
+ fail(`failed to create tag ${tagName}: ${tagResult.error.message}`);
155
+ }
156
+ if (tagResult.status !== 0) {
157
+ fail(`git tag exited with status ${tagResult.status}`);
158
+ }
159
+ return tagName;
160
+ }
161
+
162
+ function buildReleaseNotes(version) {
163
+ const lastTag = getLastTag();
164
+ const range = lastTag ? `${lastTag}..HEAD` : '';
165
+ const commits = getCommitSubjects(range);
166
+
167
+ const lines = [];
168
+ lines.push(`## v${version} - ${new Date().toISOString().slice(0, 10)}`);
169
+ lines.push('');
170
+ if (commits.length === 0) {
171
+ lines.push('- No user-facing changes recorded.');
172
+ } else {
173
+ for (const subject of commits) {
174
+ lines.push(`- ${subject}`);
175
+ }
176
+ }
177
+ lines.push('');
178
+ return lines.join('\n');
179
+ }
180
+
181
+ function updateChangelog(version) {
182
+ const releaseNotes = buildReleaseNotes(version);
183
+ const header = '# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n';
184
+ let existing = fs.existsSync(paths.changelog) ? fs.readFileSync(paths.changelog, 'utf8') : header;
185
+
186
+ if (!existing.startsWith('# Changelog')) {
187
+ existing = `${header}${existing.trim()}\n`;
188
+ }
189
+
190
+ const sectionHeader = `## v${version} - `;
191
+ if (existing.includes(sectionHeader)) {
192
+ const sectionRegex = new RegExp(`## v${escapeRegExp(version)} - [\\s\\S]*?(?=\\n## v|$)`, 'm');
193
+ existing = existing.replace(sectionRegex, releaseNotes.trim());
194
+ } else {
195
+ existing = `${header}${releaseNotes}${existing.replace(header, '')}`;
196
+ }
197
+
198
+ fs.writeFileSync(paths.changelog, normalizeTrailingNewline(existing));
199
+ }
200
+
201
+ function normalizeTrailingNewline(content) {
202
+ return `${content.trim()}\n`;
203
+ }
204
+
205
+ function escapeRegExp(value) {
206
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
207
+ }
208
+
209
+ module.exports = {
210
+ buildReleaseNotes,
211
+ bumpVersion,
212
+ createTag,
213
+ fail,
214
+ getCmdVersion,
215
+ getLastTag,
216
+ getPackageVersion,
217
+ isValidSemver,
218
+ packageRoot,
219
+ paths,
220
+ runGit,
221
+ updateChangelog,
222
+ updateVersions,
223
+ };
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const https = require('node:https');
6
+ const http = require('node:http');
7
+ const { spawnSync } = require('node:child_process');
8
+
9
+ const packageRoot = path.resolve(__dirname, '..');
10
+ const pkg = require(path.join(packageRoot, 'package.json'));
11
+ const binaryDir = path.join(packageRoot, '.npm-bin');
12
+ const binaryName = process.platform === 'win32' ? 'orch.exe' : 'orch';
13
+ const binaryPath = path.join(binaryDir, binaryName);
14
+
15
+ const targets = {
16
+ darwin: { x64: 'darwin-x64', arm64: 'darwin-arm64' },
17
+ linux: { x64: 'linux-x64', arm64: 'linux-arm64' },
18
+ win32: { x64: 'windows-x64.exe', arm64: 'windows-arm64.exe' },
19
+ };
20
+
21
+ function main() {
22
+ if (process.env.ORCH_SKIP_DOWNLOAD === '1') {
23
+ console.log('[orch] skipping binary install because ORCH_SKIP_DOWNLOAD=1');
24
+ return;
25
+ }
26
+
27
+ ensureDir(binaryDir);
28
+
29
+ if (fs.existsSync(binaryPath)) {
30
+ makeExecutable(binaryPath);
31
+ console.log(`[orch] using existing binary at ${binaryPath}`);
32
+ return;
33
+ }
34
+
35
+ install()
36
+ .then(() => {
37
+ makeExecutable(binaryPath);
38
+ console.log(`[orch] binary ready at ${binaryPath}`);
39
+ })
40
+ .catch((error) => {
41
+ console.error(`[orch] install failed: ${error.message}`);
42
+ process.exit(1);
43
+ });
44
+ }
45
+
46
+ async function install() {
47
+ const assetName = resolveAssetName();
48
+ const baseUrl = process.env.ORCH_BINARY_BASE_URL || `https://github.com/furkanbeydemir/orch/releases/download/v${pkg.version}`;
49
+ const assetUrl = `${baseUrl}/${assetName}`;
50
+
51
+ try {
52
+ console.log(`[orch] downloading ${assetUrl}`);
53
+ await downloadFile(assetUrl, binaryPath);
54
+ return;
55
+ } catch (downloadError) {
56
+ console.warn(`[orch] release download unavailable: ${downloadError.message}`);
57
+ }
58
+
59
+ buildFromSource();
60
+ }
61
+
62
+ function resolveAssetName() {
63
+ const platformTargets = targets[process.platform];
64
+ if (!platformTargets) {
65
+ throw new Error(`unsupported platform: ${process.platform}`);
66
+ }
67
+
68
+ const assetSuffix = platformTargets[process.arch];
69
+ if (!assetSuffix) {
70
+ throw new Error(`unsupported architecture: ${process.arch}`);
71
+ }
72
+
73
+ return `orch-${assetSuffix}`;
74
+ }
75
+
76
+ function downloadFile(url, destination, redirectCount = 0) {
77
+ if (redirectCount > 5) {
78
+ return Promise.reject(new Error('too many redirects'));
79
+ }
80
+
81
+ const client = url.startsWith('https://') ? https : http;
82
+
83
+ return new Promise((resolve, reject) => {
84
+ const request = client.get(url, (response) => {
85
+ if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
86
+ response.resume();
87
+ resolve(downloadFile(response.headers.location, destination, redirectCount + 1));
88
+ return;
89
+ }
90
+
91
+ if (response.statusCode !== 200) {
92
+ response.resume();
93
+ reject(new Error(`unexpected status code ${response.statusCode || 'unknown'}`));
94
+ return;
95
+ }
96
+
97
+ const file = fs.createWriteStream(destination, { mode: 0o755 });
98
+ response.pipe(file);
99
+
100
+ file.on('finish', () => {
101
+ file.close((closeError) => {
102
+ if (closeError) {
103
+ reject(closeError);
104
+ return;
105
+ }
106
+ resolve();
107
+ });
108
+ });
109
+
110
+ file.on('error', (fileError) => {
111
+ fs.rmSync(destination, { force: true });
112
+ reject(fileError);
113
+ });
114
+ });
115
+
116
+ request.on('error', (error) => {
117
+ fs.rmSync(destination, { force: true });
118
+ reject(error);
119
+ });
120
+ });
121
+ }
122
+
123
+ function buildFromSource() {
124
+ const versionResult = spawnSync('go', ['version'], {
125
+ cwd: packageRoot,
126
+ encoding: 'utf8',
127
+ });
128
+
129
+ if (versionResult.error || versionResult.status !== 0) {
130
+ throw new Error('no published binary found and `go` is not available for source build fallback');
131
+ }
132
+
133
+ console.log('[orch] building from source with local Go toolchain');
134
+ const buildResult = spawnSync('go', ['build', '-o', binaryPath, '.'], {
135
+ cwd: packageRoot,
136
+ stdio: 'inherit',
137
+ });
138
+
139
+ if (buildResult.error) {
140
+ throw buildResult.error;
141
+ }
142
+ if (buildResult.status !== 0) {
143
+ throw new Error(`go build failed with exit code ${buildResult.status}`);
144
+ }
145
+ }
146
+
147
+ function ensureDir(directory) {
148
+ fs.mkdirSync(directory, { recursive: true });
149
+ }
150
+
151
+ function makeExecutable(filePath) {
152
+ if (process.platform !== 'win32' && fs.existsSync(filePath)) {
153
+ fs.chmodSync(filePath, 0o755);
154
+ }
155
+ }
156
+
157
+ main();
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {
4
+ bumpVersion,
5
+ createTag,
6
+ fail,
7
+ getPackageVersion,
8
+ isValidSemver,
9
+ paths,
10
+ updateChangelog,
11
+ updateVersions,
12
+ } = require('./lib/release-utils');
13
+
14
+ const args = process.argv.slice(2);
15
+ const requestedVersion = (args[0] || '').trim();
16
+ const shouldTag = args.includes('--tag');
17
+ const shouldUpdateChangelog = !args.includes('--no-changelog');
18
+
19
+ if (!requestedVersion) {
20
+ fail('missing version argument. Example: npm run release:prepare -- 0.1.1 or npm run release:prepare -- patch');
21
+ }
22
+
23
+ const currentVersion = getPackageVersion();
24
+ const nextVersion = ['patch', 'minor', 'major'].includes(requestedVersion)
25
+ ? bumpVersion(currentVersion, requestedVersion)
26
+ : requestedVersion;
27
+
28
+ if (!isValidSemver(nextVersion)) {
29
+ fail(`invalid version: ${nextVersion}`);
30
+ }
31
+
32
+ updateVersions(nextVersion);
33
+ if (shouldUpdateChangelog) {
34
+ updateChangelog(nextVersion);
35
+ }
36
+
37
+ console.log(`[orch] updated version ${currentVersion} -> ${nextVersion}`);
38
+ if (shouldUpdateChangelog) {
39
+ console.log(`[orch] updated ${paths.changelog}`);
40
+ }
41
+
42
+ if (shouldTag) {
43
+ const tagName = createTag(nextVersion, [
44
+ 'package.json',
45
+ 'package-lock.json',
46
+ 'cmd/version.go',
47
+ 'CHANGELOG.md',
48
+ ]);
49
+ console.log(`[orch] created git tag ${tagName}`);
50
+ }
51
+
52
+ console.log('[orch] next steps: review changes, commit, and push the tag when ready');