Skip to content

Commit 8602587

Browse files
authored
fix: add release:clean-replace mise task for GoReleaser (#551)
- Create TypeScript-based mise task at .config/mise/tasks/release/clean-replace.ts - Support --dry-run flag to preview changes without modifying files - Support --json flag for structured output (CI/automation friendly) - Support -h/--help flag for usage documentation - Update .goreleaser.yaml to use 'mise run release:clean-replace' - Add pkg/logging to go mod tidy commands in .goreleaser.yaml The task removes any accidentally committed replace directives from go.mod files to ensure go install compatibility during releases. Using Bun/TypeScript ensures cross-platform compatibility (Windows, Linux, macOS).
1 parent 5baddc5 commit 8602587

File tree

2 files changed

+198
-1
lines changed

2 files changed

+198
-1
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#!/usr/bin/env bun
2+
// #MISE description="Remove replace directives from go.mod files for release"
3+
// #MISE alias="crp"
4+
// #USAGE flag "--dry-run" help="Show what would be done without making changes"
5+
// #USAGE flag "--json" help="Output results as JSON"
6+
7+
import { Glob } from "bun";
8+
import { readFileSync, writeFileSync } from "fs";
9+
import { parseArgs } from "util";
10+
11+
// Parse arguments
12+
const { values } = parseArgs({
13+
args: Bun.argv.slice(2),
14+
options: {
15+
"dry-run": { type: "boolean", default: false },
16+
json: { type: "boolean", default: false },
17+
help: { type: "boolean", short: "h", default: false },
18+
},
19+
strict: true,
20+
allowPositionals: false,
21+
});
22+
23+
if (values.help) {
24+
console.log(`release:clean-replace - Remove replace directives from go.mod files
25+
26+
Usage: mise run release:clean-replace [OPTIONS]
27+
28+
Options:
29+
--dry-run Show what would be done without making changes
30+
--json Output results as JSON
31+
-h, --help Show this help message
32+
33+
Description:
34+
This is a safeguard script for releases. We use go.work for local development,
35+
so replace directives should never be committed. This script ensures go install
36+
compatibility by removing any accidentally committed replace directives.
37+
38+
Examples:
39+
mise run release:clean-replace
40+
mise run release:clean-replace -- --dry-run
41+
mise run release:clean-replace -- --json`);
42+
process.exit(0);
43+
}
44+
45+
const dryRun = values["dry-run"];
46+
const jsonOutput = values.json;
47+
48+
// Colors (disabled for JSON output)
49+
const colors = {
50+
red: jsonOutput ? "" : "\x1b[0;31m",
51+
green: jsonOutput ? "" : "\x1b[0;32m",
52+
yellow: jsonOutput ? "" : "\x1b[1;33m",
53+
blue: jsonOutput ? "" : "\x1b[0;34m",
54+
reset: jsonOutput ? "" : "\x1b[0m",
55+
};
56+
57+
interface FileResult {
58+
path: string;
59+
hadReplace: boolean;
60+
modified: boolean;
61+
replaceCount: number;
62+
}
63+
64+
interface Result {
65+
success: boolean;
66+
dryRun: boolean;
67+
filesChecked: number;
68+
filesModified: number;
69+
files: FileResult[];
70+
error?: string;
71+
}
72+
73+
/**
74+
* Removes replace directives from go.mod files.
75+
*
76+
* This is a safeguard script for releases - we use go.work for local development,
77+
* so replace directives should never be committed. This script ensures go install
78+
* compatibility by removing any accidentally committed replace directives.
79+
*/
80+
async function main() {
81+
const result: Result = {
82+
success: true,
83+
dryRun,
84+
filesChecked: 0,
85+
filesModified: 0,
86+
files: [],
87+
};
88+
89+
if (!jsonOutput) {
90+
if (dryRun) {
91+
console.log(`${colors.yellow}DRY RUN:${colors.reset} No changes will be made\n`);
92+
}
93+
console.log("Checking for replace directives in go.mod files...");
94+
}
95+
96+
const glob = new Glob("**/go.mod");
97+
98+
for await (const file of glob.scan({ cwd: ".", onlyFiles: true })) {
99+
// Skip vendor and node_modules
100+
if (
101+
file.includes("node_modules/") ||
102+
file.includes("vendor/") ||
103+
file.includes(".git/")
104+
) {
105+
continue;
106+
}
107+
108+
result.filesChecked++;
109+
const content = readFileSync(file, "utf-8");
110+
111+
// Count replace directives
112+
// Matches both single-line: replace foo => bar
113+
// And multi-line blocks: replace (\n...\n)
114+
const singleLineMatches = content.match(/^replace\s+.+$/gm) || [];
115+
const multiLineMatches = content.match(/^replace\s*\([^)]*\)/gm) || [];
116+
const replaceCount = singleLineMatches.length + multiLineMatches.length;
117+
const hasReplace = replaceCount > 0;
118+
119+
const fileResult: FileResult = {
120+
path: file,
121+
hadReplace: hasReplace,
122+
modified: false,
123+
replaceCount,
124+
};
125+
126+
if (hasReplace) {
127+
if (!jsonOutput) {
128+
console.log(
129+
`${colors.yellow}${colors.reset} Found ${replaceCount} replace directive(s) in ${file}`
130+
);
131+
}
132+
133+
if (!dryRun) {
134+
// Remove single-line replace directives
135+
let newContent = content.replace(/^replace\s+.+$/gm, "");
136+
137+
// Remove multi-line replace blocks: replace (\n...\n)
138+
newContent = newContent.replace(/^replace\s*\([^)]*\)\s*$/gm, "");
139+
140+
// Clean up multiple consecutive blank lines
141+
newContent = newContent.replace(/\n{3,}/g, "\n\n");
142+
143+
writeFileSync(file, newContent);
144+
fileResult.modified = true;
145+
result.filesModified++;
146+
147+
if (!jsonOutput) {
148+
console.log(`${colors.green}${colors.reset} Removed replace directives from ${file}`);
149+
}
150+
} else {
151+
if (!jsonOutput) {
152+
console.log(`${colors.blue} Would remove ${replaceCount} replace directive(s)${colors.reset}`);
153+
}
154+
}
155+
}
156+
157+
result.files.push(fileResult);
158+
}
159+
160+
if (jsonOutput) {
161+
console.log(JSON.stringify(result, null, 2));
162+
} else {
163+
console.log("");
164+
if (dryRun) {
165+
const wouldModify = result.files.filter((f) => f.hadReplace).length;
166+
console.log(
167+
`${colors.yellow}DRY RUN:${colors.reset} Checked ${result.filesChecked} go.mod files, would modify ${wouldModify}`
168+
);
169+
} else {
170+
console.log(
171+
`${colors.green}${colors.reset} Checked ${result.filesChecked} go.mod files, modified ${result.filesModified}`
172+
);
173+
}
174+
console.log("Replace directive check complete.");
175+
}
176+
177+
return result;
178+
}
179+
180+
main().catch((err) => {
181+
if (jsonOutput) {
182+
console.log(
183+
JSON.stringify({
184+
success: false,
185+
dryRun,
186+
filesChecked: 0,
187+
filesModified: 0,
188+
files: [],
189+
error: err.message,
190+
})
191+
);
192+
} else {
193+
console.error(`${colors.red}ERROR:${colors.reset} Failed to clean replace directives:`, err.message);
194+
}
195+
process.exit(1);
196+
});

.goreleaser.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ before:
1212
hooks:
1313
# Safeguard: Remove any replace directives that may have been accidentally committed
1414
# This ensures go install compatibility
15-
- bash ./.mise/scripts/remove-replace-directives.sh
15+
- mise run release:clean-replace
1616
# Sync CHANGELOG.md for embedding in about command
1717
- cp CHANGELOG.md cmd/morphir/cmd/CHANGELOG.md
1818
# Ensure all modules have their dependencies in order
@@ -24,6 +24,7 @@ before:
2424
- go mod tidy -C pkg/bindings/wit
2525
- go mod tidy -C pkg/config
2626
- go mod tidy -C pkg/docling-doc
27+
- go mod tidy -C pkg/logging
2728
- go mod tidy -C pkg/models
2829
- go mod tidy -C pkg/nbformat
2930
- go mod tidy -C pkg/pipeline

0 commit comments

Comments
 (0)