Skip to content

Commit cbf8ff1

Browse files
committed
fix: resolve Go command execution issues and update documentation
- Fixed Go command runner environment variable handling - Switched from spawn to exec for better compatibility - Fixed syntax error in go-fmt.js arrow function - Added Go commands section to integration guide - Updated README with Go command references
1 parent d5beb59 commit cbf8ff1

4 files changed

Lines changed: 141 additions & 80 deletions

File tree

INTEGRATION-GUIDE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ everything-opencode/
4444
- **Confidence scoring**: 0-0.95 based on multiple indicators
4545
- **Python project types**: FastAPI, Django, Flask, Data Science, ML, CLI, Library
4646
- **PineScript project types**: Indicator, Strategy, Library with version detection (v4, v5, v6)
47+
- **Go project types**: CLI, Web Service, Library, Module, Workspace (Go 1.18+)
4748
- **Automatic primary language determination**
4849

4950
### 2. Interactive Configuration
@@ -80,6 +81,15 @@ everything-opencode/
8081
- **/pine-convert** - Convert between PineScript versions (v4 ↔ v5 ↔ v6)
8182
- **/pine-alert** - Configure alert system with webhooks and notifications
8283

84+
#### Go Commands
85+
86+
- **/go-setup** - Configure Go project with Go-specific improvements (CLI, web, library, workspace)
87+
- **/go-build** - Build Go projects with cross-compilation for 5 platforms and race detection
88+
- **/go-test** - Run comprehensive tests with coverage, benchmarks, and race detection
89+
- **/go-lint** - Lint code with multiple linter support (golangci-lint, staticcheck, revive)
90+
- **/go-fmt** - Format code with gofmt/goimports and formatting checks
91+
- **/go-deps** - Manage dependencies with security auditing and update management
92+
8393
## Quick Start
8494

8595
### 1. Initial Setup

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ everything-opencode/
120120
| |-- python-setup.md # /python-setup - Configure Python project
121121
| |-- pine-setup.md # /pine-setup - Configure PineScript project
122122
| |-- pine-validate.md # /pine-validate - Validate PineScript syntax
123+
| |-- go-setup.md # /go-setup - Configure Go project with Go-specific improvements
124+
| |-- go-build.md # /go-build - Build Go projects with cross-compilation
123125
|
124126
|-- rules/ # Always-follow guidelines (copy to ~/.opencode/rules/)
125127
| |-- security.md # Mandatory security checks

scripts/commands/go-fmt.js

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
#!/usr/bin/env node
22
/**
33
* /go-fmt command wrapper
4-
*
4+
*
55
* Format Go code with Go-specific improvements
66
*/
77

8-
const GoCommandRunner = require('../go/command-runner');
8+
const GoCommandRunner = require("../go/command-runner");
99

1010
async function main() {
1111
const args = process.argv.slice(2);
1212
const options = {};
13-
13+
1414
// Parse command line arguments
1515
for (let i = 0; i < args.length; i++) {
1616
const arg = args[i];
17-
18-
if (arg === '--write' || arg === '-w') {
17+
18+
if (arg === "--write" || arg === "-w") {
1919
options.write = true;
20-
} else if (arg === '--diff' || arg === '-d') {
20+
} else if (arg === "--diff" || arg === "-d") {
2121
options.diff = true;
22-
} else if (arg === '--simplify' || arg === '-s') {
22+
} else if (arg === "--simplify" || arg === "-s") {
2323
options.simplify = true;
24-
} else if (arg === '--list' || arg === '-l') {
24+
} else if (arg === "--list" || arg === "-l") {
2525
options.list = true;
26-
} else if (arg === '--formatter') {
26+
} else if (arg === "--formatter") {
2727
options.formatter = args[++i];
28-
} else if (arg === '--verbose' || arg === '-v') {
28+
} else if (arg === "--verbose" || arg === "-v") {
2929
options.verbose = true;
30-
} else if (arg === '--check') {
30+
} else if (arg === "--check") {
3131
options.check = true;
32-
} else if (arg === '--help' || arg === '-h') {
32+
} else if (arg === "--help" || arg === "-h") {
3333
showHelp();
3434
process.exit(0);
35-
} else if (arg.startsWith('--')) {
35+
} else if (arg.startsWith("--")) {
3636
console.error(`Unknown option: ${arg}`);
3737
showHelp();
3838
process.exit(1);
@@ -42,38 +42,37 @@ async function main() {
4242
options.paths.push(arg);
4343
}
4444
}
45-
45+
4646
try {
4747
const runner = new GoCommandRunner(process.cwd());
4848
await runner.initialize();
49-
49+
5050
// Override formatter from command line
5151
if (options.formatter && runner.goConfig.tools) {
5252
runner.goConfig.tools.formatter = options.formatter;
5353
}
54-
54+
5555
// Handle check mode (dry run)
5656
if (options.check) {
5757
return runFormatCheck(runner, options);
5858
}
59-
60-
console.log('🎨 Formatting Go code...');
59+
60+
console.log("🎨 Formatting Go code...");
6161
const result = await runner.format(options);
62-
62+
6363
if (result.success) {
6464
if (options.write) {
65-
console.log('\n✅ Code formatted successfully!');
65+
console.log("\n✅ Code formatted successfully!");
6666
} else if (options.diff) {
6767
// Diff output is already shown by the formatter
68-
console.log('\n📋 Formatting diff shown above');
68+
console.log("\n📋 Formatting diff shown above");
6969
} else {
70-
console.log('\n✅ Code is properly formatted!');
70+
console.log("\n✅ Code is properly formatted!");
7171
}
7272
} else {
73-
console.error('\n❌ Formatting failed');
73+
console.error("\n❌ Formatting failed");
7474
process.exit(1);
7575
}
76-
7776
} catch (error) {
7877
console.error(`❌ Formatting failed: ${error.message}`);
7978
process.exit(1);
@@ -84,46 +83,47 @@ async function main() {
8483
* Run format check (dry run)
8584
*/
8685
async function runFormatCheck(runner, options) {
87-
console.log('🔍 Checking Go code formatting...');
88-
86+
console.log("🔍 Checking Go code formatting...");
87+
8988
try {
9089
// First check with gofmt
9190
const gofmtResult = await runner.format({
9291
...options,
9392
diff: true,
9493
write: false,
95-
stdio: 'pipe'
94+
stdio: "pipe",
9695
});
97-
96+
9897
if (gofmtResult.stdout && gofmtResult.stdout.trim()) {
99-
console.log('\n⚠️ Formatting issues found:');
98+
console.log("\n⚠️ Formatting issues found:");
10099
console.log(gofmtResult.stdout);
101-
console.log('\n💡 Run /go-fmt --write to fix these issues');
100+
console.log("\n💡 Run /go-fmt --write to fix these issues");
102101
process.exit(1);
103102
} else {
104-
console.log('\n✅ All Go files are properly formatted!');
103+
console.log("\n✅ All Go files are properly formatted!");
105104
}
106-
105+
107106
// Also check imports if goimports is available
108107
if (runner.detectedTools.goimports?.installed) {
109-
console.log('\n🔍 Checking import organization...');
110-
111-
const { runCommand } = require('../lib/utils');
112-
const importResult = runCommand('goimports -d .', {
108+
console.log("\n🔍 Checking import organization...");
109+
110+
const { runCommand } = require("../lib/utils");
111+
const importResult = runCommand("goimports -d .", {
113112
cwd: runner.projectPath,
114-
stdio: 'pipe'
113+
stdio: "pipe",
115114
});
116-
115+
117116
if (importResult.stdout && importResult.stdout.trim()) {
118-
console.log('\n⚠️ Import organization issues found:');
117+
console.log("\n⚠️ Import organization issues found:");
119118
console.log(importResult.stdout);
120-
console.log('\n💡 Run /go-fmt --write --formatter goimports to fix imports');
119+
console.log(
120+
"\n💡 Run /go-fmt --write --formatter goimports to fix imports",
121+
);
121122
process.exit(1);
122123
} else {
123-
console.log('✅ Imports are properly organized!');
124+
console.log("✅ Imports are properly organized!");
124125
}
125126
}
126-
127127
} catch (error) {
128128
console.error(`❌ Format check failed: ${error.message}`);
129129
process.exit(1);
@@ -222,10 +222,10 @@ Tips:
222222
}
223223

224224
if (require.main === module) {
225-
main().catch((error) {
225+
main().catch((error) => {
226226
console.error(`Fatal error: ${error.message}`);
227227
process.exit(1);
228228
});
229229
}
230230

231-
module.exports = { main };
231+
module.exports = { main };

scripts/go/command-runner.js

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -66,62 +66,83 @@ class GoCommandRunner {
6666
* Execute Go command with Go-specific improvements
6767
*/
6868
async executeGoCommand(command, args = [], options = {}) {
69+
// Ensure critical Go environment variables are set
70+
const goEnv = {
71+
...process.env,
72+
GO111MODULE: "on",
73+
};
74+
75+
// Set HOME if not set (required for GOCACHE)
76+
if (!goEnv.HOME) {
77+
goEnv.HOME = require("os").homedir();
78+
}
79+
80+
// Set GOCACHE if not set
81+
if (!goEnv.GOCACHE) {
82+
goEnv.GOCACHE = `${goEnv.HOME}/.cache/go-build`;
83+
}
84+
6985
const defaultOptions = {
7086
cwd: this.projectPath,
7187
stdio: "inherit",
72-
env: { ...process.env, GO111MODULE: "on" },
88+
env: goEnv,
7389
timeout: 300000, // 5 minutes for Go commands
7490
};
7591

76-
const finalOptions = { ...defaultOptions, ...options };
92+
const finalOptions = {
93+
...defaultOptions,
94+
...options,
95+
// Merge environment objects instead of overwriting
96+
env: options.env
97+
? { ...defaultOptions.env, ...options.env }
98+
: defaultOptions.env,
99+
};
77100

78101
console.log(`🚀 Executing: go ${command} ${args.join(" ")}`);
79102

80-
return new Promise((resolve, reject) => {
81-
const process = spawn("go", [command, ...args], finalOptions);
82-
83-
let stdout = "";
84-
let stderr = "";
103+
// Debug: Check if go is in PATH
104+
if (finalOptions.verbose) {
105+
console.log(`🔍 PATH: ${process.env.PATH}`);
106+
console.log(
107+
`🔍 Go executable check: ${require("child_process").execSync('which go || echo "go not found"').toString()}`,
108+
);
109+
}
85110

86-
if (process.stdout) {
87-
process.stdout.on("data", (data) => {
88-
stdout += data.toString();
89-
if (finalOptions.stdio === "inherit") {
90-
process.stdout.write(data);
91-
}
92-
});
93-
}
111+
return new Promise((resolve, reject) => {
112+
const { exec } = require("child_process");
94113

95-
if (process.stderr) {
96-
process.stderr.on("data", (data) => {
97-
stderr += data.toString();
98-
if (finalOptions.stdio === "inherit") {
99-
process.stderr.write(data);
100-
}
101-
});
102-
}
114+
// Build the command string with full path to go
115+
const goPath = "/opt/homebrew/bin/go"; // Default for Apple Silicon Homebrew
116+
const cmd = `${goPath} ${command} ${args.join(" ")}`;
117+
console.log(`🔍 Executing: ${cmd}`);
118+
console.log(`🔍 CWD: ${finalOptions.cwd}`);
103119

104-
process.on("close", (code) => {
105-
if (code === 0) {
106-
resolve({ success: true, code, stdout, stderr });
107-
} else {
120+
exec(cmd, finalOptions, (error, stdout, stderr) => {
121+
if (error) {
122+
console.log(`🔍 Exec error: ${error.message}`);
108123
reject(
109-
new Error(`Go ${command} failed with code ${code}: ${stderr}`),
124+
new Error(`Failed to execute go ${command}: ${error.message}`),
110125
);
126+
} else {
127+
resolve({
128+
success: error ? false : true,
129+
code: error ? error.code : 0,
130+
stdout,
131+
stderr,
132+
});
111133
}
112134
});
113-
114-
process.on("error", (error) => {
115-
reject(new Error(`Failed to execute go ${command}: ${error.message}`));
116-
});
117135
});
118136
}
119137

120138
/**
121139
* Build Go project with Go-specific improvements
122140
*/
123141
async build(options = {}) {
124-
await this.initialize();
142+
// Only initialize if not already initialized
143+
if (!this.detectedTools) {
144+
await this.initialize();
145+
}
125146

126147
const args = [];
127148

@@ -166,10 +187,19 @@ class GoCommandRunner {
166187
args.push("-buildmode", options.buildMode);
167188
}
168189

169-
// Add build target
190+
// Handle cross-compilation via environment variables
170191
const target = options.target || this.detectBuildTarget();
171192
if (target) {
172-
args.push("-target", target);
193+
const [goos, goarch] = target.split("/");
194+
if (goos && goarch) {
195+
// Set environment variables for cross-compilation
196+
options.env = {
197+
...(options.env || {}),
198+
GOOS: goos,
199+
GOARCH: goarch,
200+
CGO_ENABLED: "0",
201+
};
202+
}
173203
}
174204

175205
// Add verbose flag
@@ -718,7 +748,26 @@ class GoCommandRunner {
718748
env: { ...process.env, GO111MODULE: "on" },
719749
};
720750

721-
const finalOptions = { ...defaultOptions, ...options };
751+
const finalOptions = {
752+
...defaultOptions,
753+
...options,
754+
// Merge environment objects instead of overwriting
755+
env: options.env
756+
? { ...defaultOptions.env, ...options.env }
757+
: defaultOptions.env,
758+
};
759+
760+
console.log(
761+
`🔍 defaultOptions.env keys: ${Object.keys(defaultOptions.env || {}).join(", ")}`,
762+
);
763+
console.log(
764+
`🔍 options.env keys: ${Object.keys(options.env || {}).join(", ")}`,
765+
);
766+
console.log(
767+
`🔍 finalOptions.env keys: ${Object.keys(finalOptions.env || {}).join(", ")}`,
768+
);
769+
console.log(`🔍 finalOptions.env.HOME: ${finalOptions.env?.HOME}`);
770+
console.log(`🔍 finalOptions.env.GOCACHE: ${finalOptions.env?.GOCACHE}`);
722771

723772
return new Promise((resolve, reject) => {
724773
const process = spawn("godoc", args, finalOptions);

0 commit comments

Comments
 (0)