@mytechtoday/augment-extensions 1.4.0 → 1.5.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/augment-extensions/coding-standards/c/CHANGELOG.md +55 -0
- package/augment-extensions/coding-standards/c/LICENSE +22 -0
- package/augment-extensions/coding-standards/c/README.md +167 -0
- package/augment-extensions/coding-standards/c/config/defaults.json +26 -0
- package/augment-extensions/coding-standards/c/config/examples/embedded.yaml +25 -0
- package/augment-extensions/coding-standards/c/config/examples/systems.json +31 -0
- package/augment-extensions/coding-standards/c/config/schema.json +244 -0
- package/augment-extensions/coding-standards/c/docs/API.md +613 -0
- package/augment-extensions/coding-standards/c/docs/CONFIGURATION.md +259 -0
- package/augment-extensions/coding-standards/c/docs/USER_GUIDE.md +567 -0
- package/augment-extensions/coding-standards/c/examples/drivers/Makefile +33 -0
- package/augment-extensions/coding-standards/c/examples/drivers/README.md +192 -0
- package/augment-extensions/coding-standards/c/examples/drivers/dma-example.c +224 -0
- package/augment-extensions/coding-standards/c/examples/drivers/example.dts +64 -0
- package/augment-extensions/coding-standards/c/examples/drivers/platform-driver.c +174 -0
- package/augment-extensions/coding-standards/c/examples/embedded/README.md +167 -0
- package/augment-extensions/coding-standards/c/examples/embedded/gpio-control.c +172 -0
- package/augment-extensions/coding-standards/c/examples/embedded/timer-isr.c +198 -0
- package/augment-extensions/coding-standards/c/examples/embedded/uart-communication.c +212 -0
- package/augment-extensions/coding-standards/c/examples/kernel/Makefile +82 -0
- package/augment-extensions/coding-standards/c/examples/kernel/README.md +168 -0
- package/augment-extensions/coding-standards/c/examples/kernel/char-device.c +198 -0
- package/augment-extensions/coding-standards/c/examples/kernel/proc-file.c +131 -0
- package/augment-extensions/coding-standards/c/examples/kernel/simple-module.c +111 -0
- package/augment-extensions/coding-standards/c/examples/legacy/Makefile +62 -0
- package/augment-extensions/coding-standards/c/examples/legacy/README.md +255 -0
- package/augment-extensions/coding-standards/c/examples/legacy/c89-to-c11-migration.c +268 -0
- package/augment-extensions/coding-standards/c/examples/legacy/compatibility-layer.c +239 -0
- package/augment-extensions/coding-standards/c/examples/networking/Makefile +35 -0
- package/augment-extensions/coding-standards/c/examples/networking/README.md +207 -0
- package/augment-extensions/coding-standards/c/examples/networking/protocol-parser.c +270 -0
- package/augment-extensions/coding-standards/c/examples/networking/tcp-server.c +197 -0
- package/augment-extensions/coding-standards/c/examples/networking/udp-multicast.c +220 -0
- package/augment-extensions/coding-standards/c/examples/realtime/Makefile +53 -0
- package/augment-extensions/coding-standards/c/examples/realtime/README.md +199 -0
- package/augment-extensions/coding-standards/c/examples/realtime/deadline-monitoring.c +260 -0
- package/augment-extensions/coding-standards/c/examples/realtime/priority-scheduling.c +258 -0
- package/augment-extensions/coding-standards/c/examples/systems/Makefile +34 -0
- package/augment-extensions/coding-standards/c/examples/systems/README.md +123 -0
- package/augment-extensions/coding-standards/c/examples/systems/ipc-pipes.c +181 -0
- package/augment-extensions/coding-standards/c/examples/systems/process-management.c +153 -0
- package/augment-extensions/coding-standards/c/examples/systems/signal-handling.c +162 -0
- package/augment-extensions/coding-standards/c/module.json +149 -0
- package/augment-extensions/coding-standards/c/rules/categories/drivers.md +635 -0
- package/augment-extensions/coding-standards/c/rules/categories/embedded.md +510 -0
- package/augment-extensions/coding-standards/c/rules/categories/kernel.md +653 -0
- package/augment-extensions/coding-standards/c/rules/categories/legacy.md +526 -0
- package/augment-extensions/coding-standards/c/rules/categories/networking.md +735 -0
- package/augment-extensions/coding-standards/c/rules/categories/realtime.md +631 -0
- package/augment-extensions/coding-standards/c/rules/categories/systems.md +586 -0
- package/augment-extensions/coding-standards/c/rules/universal/const-correctness.md +275 -0
- package/augment-extensions/coding-standards/c/rules/universal/documentation.md +251 -0
- package/augment-extensions/coding-standards/c/rules/universal/error-handling.md +250 -0
- package/augment-extensions/coding-standards/c/rules/universal/header-guards.md +254 -0
- package/augment-extensions/coding-standards/c/rules/universal/memory-safety.md +233 -0
- package/augment-extensions/coding-standards/c/rules/universal/naming.md +146 -0
- package/augment-extensions/coding-standards/c/src/conflict-detector.ts +461 -0
- package/augment-extensions/coding-standards/c/src/prompt-generator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-evaluator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-override.ts +427 -0
- package/augment-extensions/coding-standards/c/src/template-engine.ts +217 -0
- package/augment-extensions/coding-standards/c/templates/prompts/drivers.txt +191 -0
- package/augment-extensions/coding-standards/c/templates/prompts/embedded.txt +164 -0
- package/augment-extensions/coding-standards/c/templates/prompts/kernel.txt +175 -0
- package/augment-extensions/coding-standards/c/templates/prompts/legacy.txt +280 -0
- package/augment-extensions/coding-standards/c/templates/prompts/networking.txt +259 -0
- package/augment-extensions/coding-standards/c/templates/prompts/realtime.txt +219 -0
- package/augment-extensions/coding-standards/c/templates/prompts/systems.txt +147 -0
- package/augment-extensions/coding-standards/c/tests/integration/category-specific.test.ts +356 -0
- package/augment-extensions/coding-standards/c/tests/integration/end-to-end-workflow.test.ts +377 -0
- package/augment-extensions/coding-standards/c/tests/performance/benchmarks.test.ts +407 -0
- package/augment-extensions/coding-standards/c/tests/unit/config-manager.test.ts +345 -0
- package/augment-extensions/coding-standards/c/tests/unit/conflict-detector.test.ts +294 -0
- package/augment-extensions/coding-standards/c/tests/unit/prompt-generator.test.ts +174 -0
- package/augment-extensions/coding-standards/c/tests/unit/registry.test.ts +313 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-evaluator.test.ts +318 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-override.test.ts +326 -0
- package/augment-extensions/coding-standards/c/tests/unit/template-engine.test.ts +314 -0
- package/augment-extensions/coding-standards/go/CHARACTER-COUNT-REPORT.md +135 -0
- package/augment-extensions/coding-standards/go/PHASE1-COMPLETION.md +146 -0
- package/augment-extensions/coding-standards/go/PHASE4-COMPLETION.md +184 -0
- package/augment-extensions/coding-standards/go/README.md +200 -0
- package/augment-extensions/coding-standards/go/VALIDATION-CHECKLIST.md +154 -0
- package/augment-extensions/coding-standards/go/config/examples/example-cli.json +15 -0
- package/augment-extensions/coding-standards/go/config/examples/example-microservices.json +21 -0
- package/augment-extensions/coding-standards/go/config/examples/example-multi-category.yaml +24 -0
- package/augment-extensions/coding-standards/go/config/examples/example-web.json +15 -0
- package/augment-extensions/coding-standards/go/config/schema.json +110 -0
- package/augment-extensions/coding-standards/go/docs/CATEGORIES.md +221 -0
- package/augment-extensions/coding-standards/go/docs/CONFIGURATION.md +198 -0
- package/augment-extensions/coding-standards/go/docs/TROUBLESHOOTING.md +285 -0
- package/augment-extensions/coding-standards/go/examples/cli/cobra-app.go +287 -0
- package/augment-extensions/coding-standards/go/examples/cloud-native-app.go +217 -0
- package/augment-extensions/coding-standards/go/examples/devops-tool.go +250 -0
- package/augment-extensions/coding-standards/go/examples/distributed-system.go +247 -0
- package/augment-extensions/coding-standards/go/examples/microservices/grpc-service.go +253 -0
- package/augment-extensions/coding-standards/go/examples/rest-api.go +270 -0
- package/augment-extensions/coding-standards/go/examples/web/http-server.go +224 -0
- package/augment-extensions/coding-standards/go/module.json +139 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/api-versioning.md +149 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rate-limiting.md +209 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rest-api-design.md +183 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/cloud-config.md +193 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/health-checks.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/kubernetes.md +180 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/automation.md +179 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/ci-cd-integration.md +147 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/infrastructure-as-code.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/caching.md +150 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/consensus.md +187 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/event-sourcing.md +246 -0
- package/augment-extensions/coding-standards/go/rules/cli/command-parsing.md +264 -0
- package/augment-extensions/coding-standards/go/rules/cli/configuration.md +268 -0
- package/augment-extensions/coding-standards/go/rules/cli/cross-platform.md +324 -0
- package/augment-extensions/coding-standards/go/rules/microservices/distributed-tracing.md +253 -0
- package/augment-extensions/coding-standards/go/rules/microservices/grpc.md +257 -0
- package/augment-extensions/coding-standards/go/rules/microservices/metrics.md +278 -0
- package/augment-extensions/coding-standards/go/rules/microservices/service-discovery.md +249 -0
- package/augment-extensions/coding-standards/go/rules/universal/code-organization.md +221 -0
- package/augment-extensions/coding-standards/go/rules/universal/documentation.md +269 -0
- package/augment-extensions/coding-standards/go/rules/universal/performance.md +323 -0
- package/augment-extensions/coding-standards/go/rules/universal/testing.md +162 -0
- package/augment-extensions/coding-standards/go/rules/web/graceful-shutdown.md +249 -0
- package/augment-extensions/coding-standards/go/rules/web/http-handlers.md +164 -0
- package/augment-extensions/coding-standards/go/rules/web/middleware.md +234 -0
- package/augment-extensions/coding-standards/go/rules/web/routing.md +251 -0
- package/augment-extensions/coding-standards/go/templates/prompts/api.md +160 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cli.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cloud-native.md +121 -0
- package/augment-extensions/coding-standards/go/templates/prompts/devops.md +146 -0
- package/augment-extensions/coding-standards/go/templates/prompts/distributed.md +133 -0
- package/augment-extensions/coding-standards/go/templates/prompts/microservices.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/web.md +181 -0
- package/augment-extensions/coding-standards/go/tests/integration/module-integration.test.ts +164 -0
- package/augment-extensions/coding-standards/go/tests/unit/category-selection.test.ts +147 -0
- package/augment-extensions/coding-standards/go/tests/unit/module-structure.test.ts +154 -0
- package/augment-extensions/coding-standards/go/tests/validate-character-count.ps1 +13 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.ps1 +148 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.sh +135 -0
- package/cli/dist/analysis/ast-parser.d.ts +47 -0
- package/cli/dist/analysis/ast-parser.d.ts.map +1 -0
- package/cli/dist/analysis/ast-parser.js +161 -0
- package/cli/dist/analysis/ast-parser.js.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts +27 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.js +189 -0
- package/cli/dist/analysis/complexity-analyzer.js.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts +23 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.js +237 -0
- package/cli/dist/analysis/dependency-analyzer.js.map +1 -0
- package/cli/dist/analysis/index.d.ts +9 -0
- package/cli/dist/analysis/index.d.ts.map +1 -0
- package/cli/dist/analysis/index.js +25 -0
- package/cli/dist/analysis/index.js.map +1 -0
- package/cli/dist/analysis/security-scanner.d.ts +11 -0
- package/cli/dist/analysis/security-scanner.d.ts.map +1 -0
- package/cli/dist/analysis/security-scanner.js +294 -0
- package/cli/dist/analysis/security-scanner.js.map +1 -0
- package/cli/dist/analysis/types.d.ts +151 -0
- package/cli/dist/analysis/types.d.ts.map +1 -0
- package/cli/dist/analysis/types.js +6 -0
- package/cli/dist/analysis/types.js.map +1 -0
- package/cli/dist/cli.js +24 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/code-analysis.d.ts +11 -0
- package/cli/dist/commands/code-analysis.d.ts.map +1 -0
- package/cli/dist/commands/code-analysis.js +412 -0
- package/cli/dist/commands/code-analysis.js.map +1 -0
- package/modules.md +99 -3
- package/package.json +14 -2
- package/cli/dist/commands/agent.d.ts +0 -37
- package/cli/dist/commands/agent.d.ts.map +0 -1
- package/cli/dist/commands/agent.js +0 -222
- package/cli/dist/commands/agent.js.map +0 -1
- package/cli/dist/commands/beads.d.ts +0 -64
- package/cli/dist/commands/beads.d.ts.map +0 -1
- package/cli/dist/commands/beads.js +0 -377
- package/cli/dist/commands/beads.js.map +0 -1
- package/cli/dist/commands/change.d.ts +0 -54
- package/cli/dist/commands/change.d.ts.map +0 -1
- package/cli/dist/commands/change.js +0 -243
- package/cli/dist/commands/change.js.map +0 -1
- package/cli/dist/commands/clean.d.ts +0 -15
- package/cli/dist/commands/clean.d.ts.map +0 -1
- package/cli/dist/commands/clean.js +0 -63
- package/cli/dist/commands/clean.js.map +0 -1
- package/cli/dist/commands/clone.d.ts +0 -15
- package/cli/dist/commands/clone.d.ts.map +0 -1
- package/cli/dist/commands/clone.js +0 -49
- package/cli/dist/commands/clone.js.map +0 -1
- package/cli/dist/commands/config.d.ts +0 -33
- package/cli/dist/commands/config.d.ts.map +0 -1
- package/cli/dist/commands/config.js +0 -166
- package/cli/dist/commands/config.js.map +0 -1
- package/cli/dist/commands/context.d.ts +0 -38
- package/cli/dist/commands/context.d.ts.map +0 -1
- package/cli/dist/commands/context.js +0 -205
- package/cli/dist/commands/context.js.map +0 -1
- package/cli/dist/commands/create.d.ts +0 -18
- package/cli/dist/commands/create.d.ts.map +0 -1
- package/cli/dist/commands/create.js +0 -178
- package/cli/dist/commands/create.js.map +0 -1
- package/cli/dist/commands/diff.d.ts +0 -19
- package/cli/dist/commands/diff.d.ts.map +0 -1
- package/cli/dist/commands/diff.js +0 -104
- package/cli/dist/commands/diff.js.map +0 -1
- package/cli/dist/commands/doctor.d.ts +0 -14
- package/cli/dist/commands/doctor.d.ts.map +0 -1
- package/cli/dist/commands/doctor.js +0 -62
- package/cli/dist/commands/doctor.js.map +0 -1
- package/cli/dist/commands/export.d.ts +0 -28
- package/cli/dist/commands/export.d.ts.map +0 -1
- package/cli/dist/commands/export.js +0 -135
- package/cli/dist/commands/export.js.map +0 -1
- package/cli/dist/commands/import.d.ts +0 -23
- package/cli/dist/commands/import.d.ts.map +0 -1
- package/cli/dist/commands/import.js +0 -118
- package/cli/dist/commands/import.js.map +0 -1
- package/cli/dist/commands/prompt.d.ts +0 -45
- package/cli/dist/commands/prompt.d.ts.map +0 -1
- package/cli/dist/commands/prompt.js +0 -223
- package/cli/dist/commands/prompt.js.map +0 -1
- package/cli/dist/commands/spec.d.ts +0 -57
- package/cli/dist/commands/spec.d.ts.map +0 -1
- package/cli/dist/commands/spec.js +0 -279
- package/cli/dist/commands/spec.js.map +0 -1
- package/cli/dist/commands/stats.d.ts +0 -18
- package/cli/dist/commands/stats.d.ts.map +0 -1
- package/cli/dist/commands/stats.js +0 -85
- package/cli/dist/commands/stats.js.map +0 -1
- package/cli/dist/commands/task.d.ts +0 -65
- package/cli/dist/commands/task.d.ts.map +0 -1
- package/cli/dist/commands/task.js +0 -282
- package/cli/dist/commands/task.js.map +0 -1
- package/cli/dist/commands/template.d.ts +0 -17
- package/cli/dist/commands/template.d.ts.map +0 -1
- package/cli/dist/commands/template.js +0 -55
- package/cli/dist/commands/template.js.map +0 -1
- package/cli/dist/utils/agent-config.d.ts +0 -129
- package/cli/dist/utils/agent-config.d.ts.map +0 -1
- package/cli/dist/utils/agent-config.js +0 -297
- package/cli/dist/utils/agent-config.js.map +0 -1
- package/cli/dist/utils/beads-graph.d.ts +0 -17
- package/cli/dist/utils/beads-graph.d.ts.map +0 -1
- package/cli/dist/utils/beads-graph.js +0 -150
- package/cli/dist/utils/beads-graph.js.map +0 -1
- package/cli/dist/utils/beads-integration.d.ts +0 -112
- package/cli/dist/utils/beads-integration.d.ts.map +0 -1
- package/cli/dist/utils/beads-integration.js +0 -312
- package/cli/dist/utils/beads-integration.js.map +0 -1
- package/cli/dist/utils/beads-reporter.d.ts +0 -17
- package/cli/dist/utils/beads-reporter.d.ts.map +0 -1
- package/cli/dist/utils/beads-reporter.js +0 -160
- package/cli/dist/utils/beads-reporter.js.map +0 -1
- package/cli/dist/utils/cache-manager.d.ts +0 -55
- package/cli/dist/utils/cache-manager.d.ts.map +0 -1
- package/cli/dist/utils/cache-manager.js +0 -150
- package/cli/dist/utils/cache-manager.js.map +0 -1
- package/cli/dist/utils/change-manager.d.ts +0 -70
- package/cli/dist/utils/change-manager.d.ts.map +0 -1
- package/cli/dist/utils/change-manager.js +0 -412
- package/cli/dist/utils/change-manager.js.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.d.ts +0 -66
- package/cli/dist/utils/config-manager-enhanced.d.ts.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.js +0 -77
- package/cli/dist/utils/config-manager-enhanced.js.map +0 -1
- package/cli/dist/utils/context-manager.d.ts +0 -96
- package/cli/dist/utils/context-manager.d.ts.map +0 -1
- package/cli/dist/utils/context-manager.js +0 -258
- package/cli/dist/utils/context-manager.js.map +0 -1
- package/cli/dist/utils/diff-engine.d.ts +0 -78
- package/cli/dist/utils/diff-engine.d.ts.map +0 -1
- package/cli/dist/utils/diff-engine.js +0 -233
- package/cli/dist/utils/diff-engine.js.map +0 -1
- package/cli/dist/utils/export-system.d.ts +0 -101
- package/cli/dist/utils/export-system.d.ts.map +0 -1
- package/cli/dist/utils/export-system.js +0 -289
- package/cli/dist/utils/export-system.js.map +0 -1
- package/cli/dist/utils/health-checker.d.ts +0 -66
- package/cli/dist/utils/health-checker.d.ts.map +0 -1
- package/cli/dist/utils/health-checker.js +0 -285
- package/cli/dist/utils/health-checker.js.map +0 -1
- package/cli/dist/utils/import-system.d.ts +0 -74
- package/cli/dist/utils/import-system.d.ts.map +0 -1
- package/cli/dist/utils/import-system.js +0 -317
- package/cli/dist/utils/import-system.js.map +0 -1
- package/cli/dist/utils/module-cloner.d.ts +0 -40
- package/cli/dist/utils/module-cloner.d.ts.map +0 -1
- package/cli/dist/utils/module-cloner.js +0 -136
- package/cli/dist/utils/module-cloner.js.map +0 -1
- package/cli/dist/utils/prompt-manager.d.ts +0 -90
- package/cli/dist/utils/prompt-manager.d.ts.map +0 -1
- package/cli/dist/utils/prompt-manager.js +0 -302
- package/cli/dist/utils/prompt-manager.js.map +0 -1
- package/cli/dist/utils/spec-manager.d.ts +0 -65
- package/cli/dist/utils/spec-manager.d.ts.map +0 -1
- package/cli/dist/utils/spec-manager.js +0 -329
- package/cli/dist/utils/spec-manager.js.map +0 -1
- package/cli/dist/utils/stats-collector.d.ts +0 -74
- package/cli/dist/utils/stats-collector.d.ts.map +0 -1
- package/cli/dist/utils/stats-collector.js +0 -164
- package/cli/dist/utils/stats-collector.js.map +0 -1
- package/cli/dist/utils/template-engine.d.ts +0 -47
- package/cli/dist/utils/template-engine.d.ts.map +0 -1
- package/cli/dist/utils/template-engine.js +0 -204
- package/cli/dist/utils/template-engine.js.map +0 -1
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Go CLI Tools - Configuration Management
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Configuration management enables CLI tools to be customized through config files, environment variables, and command-line flags. This document defines best practices using Viper.
|
|
6
|
+
|
|
7
|
+
## Core Principles
|
|
8
|
+
|
|
9
|
+
1. **Precedence**: Flags > Environment Variables > Config File > Defaults
|
|
10
|
+
2. **Multiple Formats**: Support YAML, JSON, TOML config files
|
|
11
|
+
3. **Environment Variables**: Use consistent naming conventions
|
|
12
|
+
4. **Validation**: Validate configuration on load
|
|
13
|
+
5. **Documentation**: Document all configuration options
|
|
14
|
+
|
|
15
|
+
## Rules
|
|
16
|
+
|
|
17
|
+
### GOL.3.3.2.1: Use Viper for Configuration
|
|
18
|
+
|
|
19
|
+
**Rule**: Use Viper library for configuration management.
|
|
20
|
+
|
|
21
|
+
**Severity**: WARNING
|
|
22
|
+
|
|
23
|
+
**Rationale**: Viper provides unified configuration from multiple sources with proper precedence.
|
|
24
|
+
|
|
25
|
+
**✅ Good**:
|
|
26
|
+
```go
|
|
27
|
+
import (
|
|
28
|
+
"github.com/spf13/viper"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
func initConfig() error {
|
|
32
|
+
// Set config file name and paths
|
|
33
|
+
viper.SetConfigName("config")
|
|
34
|
+
viper.SetConfigType("yaml")
|
|
35
|
+
viper.AddConfigPath(".")
|
|
36
|
+
viper.AddConfigPath("$HOME/.myapp")
|
|
37
|
+
viper.AddConfigPath("/etc/myapp")
|
|
38
|
+
|
|
39
|
+
// Set defaults
|
|
40
|
+
viper.SetDefault("server.port", 8080)
|
|
41
|
+
viper.SetDefault("server.host", "localhost")
|
|
42
|
+
viper.SetDefault("log.level", "info")
|
|
43
|
+
|
|
44
|
+
// Read config file
|
|
45
|
+
if err := viper.ReadInConfig(); err != nil {
|
|
46
|
+
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
|
47
|
+
return err
|
|
48
|
+
}
|
|
49
|
+
// Config file not found; using defaults
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return nil
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### GOL.3.3.2.2: Support Environment Variables
|
|
57
|
+
|
|
58
|
+
**Rule**: Support environment variables with consistent naming (uppercase, underscore-separated).
|
|
59
|
+
|
|
60
|
+
**Severity**: WARNING
|
|
61
|
+
|
|
62
|
+
**Rationale**: Environment variables enable configuration in containerized environments.
|
|
63
|
+
|
|
64
|
+
**✅ Good**:
|
|
65
|
+
```go
|
|
66
|
+
func initConfig() error {
|
|
67
|
+
// Bind environment variables
|
|
68
|
+
viper.SetEnvPrefix("MYAPP")
|
|
69
|
+
viper.AutomaticEnv()
|
|
70
|
+
|
|
71
|
+
// Replace dots with underscores in env vars
|
|
72
|
+
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
73
|
+
|
|
74
|
+
// Now these work:
|
|
75
|
+
// MYAPP_SERVER_PORT=9000
|
|
76
|
+
// MYAPP_LOG_LEVEL=debug
|
|
77
|
+
|
|
78
|
+
return viper.ReadInConfig()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Usage:
|
|
82
|
+
// export MYAPP_SERVER_PORT=9000
|
|
83
|
+
// export MYAPP_LOG_LEVEL=debug
|
|
84
|
+
// myapp serve
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### GOL.3.3.2.3: Implement Configuration Precedence
|
|
88
|
+
|
|
89
|
+
**Rule**: Follow standard precedence: Flags > Env Vars > Config File > Defaults.
|
|
90
|
+
|
|
91
|
+
**Severity**: ERROR
|
|
92
|
+
|
|
93
|
+
**Rationale**: Predictable precedence enables flexible configuration.
|
|
94
|
+
|
|
95
|
+
**✅ Good**:
|
|
96
|
+
```go
|
|
97
|
+
var (
|
|
98
|
+
cfgFile string
|
|
99
|
+
port int
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
func init() {
|
|
103
|
+
cobra.OnInitialize(initConfig)
|
|
104
|
+
|
|
105
|
+
// Config file flag
|
|
106
|
+
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.myapp.yaml)")
|
|
107
|
+
|
|
108
|
+
// Port flag
|
|
109
|
+
rootCmd.PersistentFlags().IntVar(&port, "port", 0, "server port")
|
|
110
|
+
viper.BindPFlag("server.port", rootCmd.PersistentFlags().Lookup("port"))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
func initConfig() {
|
|
114
|
+
if cfgFile != "" {
|
|
115
|
+
viper.SetConfigFile(cfgFile)
|
|
116
|
+
} else {
|
|
117
|
+
viper.AddConfigPath("$HOME")
|
|
118
|
+
viper.SetConfigName(".myapp")
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
viper.SetEnvPrefix("MYAPP")
|
|
122
|
+
viper.AutomaticEnv()
|
|
123
|
+
|
|
124
|
+
// Set defaults
|
|
125
|
+
viper.SetDefault("server.port", 8080)
|
|
126
|
+
|
|
127
|
+
viper.ReadInConfig()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Precedence:
|
|
131
|
+
// 1. --port 9000 (flag)
|
|
132
|
+
// 2. MYAPP_SERVER_PORT=9000 (env var)
|
|
133
|
+
// 3. server.port: 9000 (config file)
|
|
134
|
+
// 4. 8080 (default)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### GOL.3.3.2.4: Validate Configuration
|
|
138
|
+
|
|
139
|
+
**Rule**: Validate configuration after loading and provide clear error messages.
|
|
140
|
+
|
|
141
|
+
**Severity**: ERROR
|
|
142
|
+
|
|
143
|
+
**Rationale**: Early validation prevents runtime errors.
|
|
144
|
+
|
|
145
|
+
**✅ Good**:
|
|
146
|
+
```go
|
|
147
|
+
type Config struct {
|
|
148
|
+
Server ServerConfig `mapstructure:"server"`
|
|
149
|
+
Log LogConfig `mapstructure:"log"`
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
type ServerConfig struct {
|
|
153
|
+
Host string `mapstructure:"host"`
|
|
154
|
+
Port int `mapstructure:"port"`
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type LogConfig struct {
|
|
158
|
+
Level string `mapstructure:"level"`
|
|
159
|
+
Format string `mapstructure:"format"`
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
func loadConfig() (*Config, error) {
|
|
163
|
+
var cfg Config
|
|
164
|
+
|
|
165
|
+
if err := viper.Unmarshal(&cfg); err != nil {
|
|
166
|
+
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Validate
|
|
170
|
+
if err := validateConfig(&cfg); err != nil {
|
|
171
|
+
return nil, err
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return &cfg, nil
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
func validateConfig(cfg *Config) error {
|
|
178
|
+
if cfg.Server.Port < 1 || cfg.Server.Port > 65535 {
|
|
179
|
+
return fmt.Errorf("invalid port: %d (must be 1-65535)", cfg.Server.Port)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
validLevels := map[string]bool{"debug": true, "info": true, "warn": true, "error": true}
|
|
183
|
+
if !validLevels[cfg.Log.Level] {
|
|
184
|
+
return fmt.Errorf("invalid log level: %s", cfg.Log.Level)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return nil
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### GOL.3.3.2.5: Support Multiple Config Formats
|
|
192
|
+
|
|
193
|
+
**Rule**: Support YAML, JSON, and TOML configuration files.
|
|
194
|
+
|
|
195
|
+
**Severity**: INFO
|
|
196
|
+
|
|
197
|
+
**✅ Good**:
|
|
198
|
+
```go
|
|
199
|
+
func initConfig() error {
|
|
200
|
+
viper.SetConfigName("config")
|
|
201
|
+
|
|
202
|
+
// Viper automatically detects format by extension
|
|
203
|
+
viper.AddConfigPath(".")
|
|
204
|
+
|
|
205
|
+
// Supports:
|
|
206
|
+
// config.yaml
|
|
207
|
+
// config.json
|
|
208
|
+
// config.toml
|
|
209
|
+
|
|
210
|
+
return viper.ReadInConfig()
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Example config.yaml**:
|
|
215
|
+
```yaml
|
|
216
|
+
server:
|
|
217
|
+
host: localhost
|
|
218
|
+
port: 8080
|
|
219
|
+
|
|
220
|
+
log:
|
|
221
|
+
level: info
|
|
222
|
+
format: json
|
|
223
|
+
|
|
224
|
+
database:
|
|
225
|
+
host: localhost
|
|
226
|
+
port: 5432
|
|
227
|
+
name: myapp
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### GOL.3.3.2.6: Provide Config File Generation
|
|
231
|
+
|
|
232
|
+
**Rule**: Provide command to generate sample configuration file.
|
|
233
|
+
|
|
234
|
+
**Severity**: INFO
|
|
235
|
+
|
|
236
|
+
**✅ Good**:
|
|
237
|
+
```go
|
|
238
|
+
var configInitCmd = &cobra.Command{
|
|
239
|
+
Use: "init-config",
|
|
240
|
+
Short: "Generate sample configuration file",
|
|
241
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
242
|
+
configPath := viper.ConfigFileUsed()
|
|
243
|
+
if configPath == "" {
|
|
244
|
+
configPath = "$HOME/.myapp.yaml"
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Set default values
|
|
248
|
+
viper.SetDefault("server.host", "localhost")
|
|
249
|
+
viper.SetDefault("server.port", 8080)
|
|
250
|
+
viper.SetDefault("log.level", "info")
|
|
251
|
+
|
|
252
|
+
// Write config file
|
|
253
|
+
if err := viper.SafeWriteConfigAs(configPath); err != nil {
|
|
254
|
+
return fmt.Errorf("failed to write config: %w", err)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
fmt.Printf("Configuration file created: %s\n", configPath)
|
|
258
|
+
return nil
|
|
259
|
+
},
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## References
|
|
264
|
+
|
|
265
|
+
- [Viper Documentation](https://github.com/spf13/viper)
|
|
266
|
+
- [12-Factor App Config](https://12factor.net/config)
|
|
267
|
+
- [Configuration Best Practices](https://blog.gopheracademy.com/advent-2014/configuration-with-fangs/)
|
|
268
|
+
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# Go CLI Tools - Cross-Platform Compatibility
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Cross-platform compatibility ensures CLI tools work correctly on Windows, macOS, and Linux. This document defines best practices for writing portable CLI applications.
|
|
6
|
+
|
|
7
|
+
## Core Principles
|
|
8
|
+
|
|
9
|
+
1. **Path Handling**: Use `filepath` package for path operations
|
|
10
|
+
2. **Exit Codes**: Use standard exit codes (0 for success, non-zero for errors)
|
|
11
|
+
3. **Signal Handling**: Handle OS signals gracefully
|
|
12
|
+
4. **Line Endings**: Handle different line ending conventions
|
|
13
|
+
5. **File Permissions**: Handle platform-specific file permissions
|
|
14
|
+
|
|
15
|
+
## Rules
|
|
16
|
+
|
|
17
|
+
### GOL.3.3.3.1: Use filepath Package for Paths
|
|
18
|
+
|
|
19
|
+
**Rule**: Always use `filepath` package for file path operations.
|
|
20
|
+
|
|
21
|
+
**Severity**: ERROR
|
|
22
|
+
|
|
23
|
+
**Rationale**: `filepath` handles platform-specific path separators and conventions.
|
|
24
|
+
|
|
25
|
+
**✅ Good**:
|
|
26
|
+
```go
|
|
27
|
+
import (
|
|
28
|
+
"path/filepath"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
func getConfigPath() string {
|
|
32
|
+
home, _ := os.UserHomeDir()
|
|
33
|
+
// Automatically uses correct separator (/ or \)
|
|
34
|
+
return filepath.Join(home, ".myapp", "config.yaml")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func findFiles(dir string) ([]string, error) {
|
|
38
|
+
pattern := filepath.Join(dir, "*.txt")
|
|
39
|
+
return filepath.Glob(pattern)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func cleanPath(path string) string {
|
|
43
|
+
// Normalizes path for current OS
|
|
44
|
+
return filepath.Clean(path)
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**❌ Bad**:
|
|
49
|
+
```go
|
|
50
|
+
// Hard-coded Unix paths don't work on Windows
|
|
51
|
+
configPath := home + "/.myapp/config.yaml"
|
|
52
|
+
|
|
53
|
+
// String concatenation breaks on Windows
|
|
54
|
+
dataPath := dir + "/" + filename
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### GOL.3.3.3.2: Use Standard Exit Codes
|
|
58
|
+
|
|
59
|
+
**Rule**: Use standard exit codes: 0 for success, 1-255 for errors.
|
|
60
|
+
|
|
61
|
+
**Severity**: ERROR
|
|
62
|
+
|
|
63
|
+
**Rationale**: Standard exit codes enable proper error handling in scripts and CI/CD.
|
|
64
|
+
|
|
65
|
+
**✅ Good**:
|
|
66
|
+
```go
|
|
67
|
+
const (
|
|
68
|
+
ExitSuccess = 0
|
|
69
|
+
ExitError = 1
|
|
70
|
+
ExitUsageError = 2
|
|
71
|
+
ExitConfigError = 3
|
|
72
|
+
ExitNetworkError = 4
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
func main() {
|
|
76
|
+
if err := rootCmd.Execute(); err != nil {
|
|
77
|
+
switch err.(type) {
|
|
78
|
+
case *UsageError:
|
|
79
|
+
os.Exit(ExitUsageError)
|
|
80
|
+
case *ConfigError:
|
|
81
|
+
os.Exit(ExitConfigError)
|
|
82
|
+
default:
|
|
83
|
+
os.Exit(ExitError)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
os.Exit(ExitSuccess)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// In commands
|
|
90
|
+
func runCommand() error {
|
|
91
|
+
if err := validateConfig(); err != nil {
|
|
92
|
+
return &ConfigError{err}
|
|
93
|
+
}
|
|
94
|
+
return nil
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### GOL.3.3.3.3: Handle OS Signals Gracefully
|
|
99
|
+
|
|
100
|
+
**Rule**: Handle SIGINT and SIGTERM for graceful shutdown on all platforms.
|
|
101
|
+
|
|
102
|
+
**Severity**: WARNING
|
|
103
|
+
|
|
104
|
+
**Rationale**: Enables clean shutdown and resource cleanup.
|
|
105
|
+
|
|
106
|
+
**✅ Good**:
|
|
107
|
+
```go
|
|
108
|
+
import (
|
|
109
|
+
"os/signal"
|
|
110
|
+
"syscall"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
func runServer(ctx context.Context) error {
|
|
114
|
+
// Create signal channel
|
|
115
|
+
sigChan := make(chan os.Signal, 1)
|
|
116
|
+
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
|
117
|
+
|
|
118
|
+
// Start server
|
|
119
|
+
srv := startServer()
|
|
120
|
+
|
|
121
|
+
// Wait for signal
|
|
122
|
+
select {
|
|
123
|
+
case <-sigChan:
|
|
124
|
+
fmt.Println("\nShutdown signal received")
|
|
125
|
+
return srv.Shutdown(ctx)
|
|
126
|
+
case <-ctx.Done():
|
|
127
|
+
return ctx.Err()
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// For long-running operations
|
|
132
|
+
func processWithCancellation(ctx context.Context) error {
|
|
133
|
+
sigChan := make(chan os.Signal, 1)
|
|
134
|
+
signal.Notify(sigChan, os.Interrupt)
|
|
135
|
+
|
|
136
|
+
done := make(chan error, 1)
|
|
137
|
+
go func() {
|
|
138
|
+
done <- doWork(ctx)
|
|
139
|
+
}()
|
|
140
|
+
|
|
141
|
+
select {
|
|
142
|
+
case err := <-done:
|
|
143
|
+
return err
|
|
144
|
+
case <-sigChan:
|
|
145
|
+
fmt.Println("\nOperation cancelled")
|
|
146
|
+
return fmt.Errorf("cancelled by user")
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### GOL.3.3.3.4: Handle Platform-Specific Features
|
|
152
|
+
|
|
153
|
+
**Rule**: Use build tags or runtime checks for platform-specific code.
|
|
154
|
+
|
|
155
|
+
**Severity**: WARNING
|
|
156
|
+
|
|
157
|
+
**✅ Good - Build Tags**:
|
|
158
|
+
```go
|
|
159
|
+
// file_unix.go
|
|
160
|
+
//go:build unix
|
|
161
|
+
|
|
162
|
+
package main
|
|
163
|
+
|
|
164
|
+
import "syscall"
|
|
165
|
+
|
|
166
|
+
func setPlatformSpecific() {
|
|
167
|
+
// Unix-specific code
|
|
168
|
+
syscall.Umask(0077)
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```go
|
|
173
|
+
// file_windows.go
|
|
174
|
+
//go:build windows
|
|
175
|
+
|
|
176
|
+
package main
|
|
177
|
+
|
|
178
|
+
func setPlatformSpecific() {
|
|
179
|
+
// Windows-specific code
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**✅ Good - Runtime Checks**:
|
|
184
|
+
```go
|
|
185
|
+
import "runtime"
|
|
186
|
+
|
|
187
|
+
func getEditor() string {
|
|
188
|
+
if runtime.GOOS == "windows" {
|
|
189
|
+
return "notepad.exe"
|
|
190
|
+
}
|
|
191
|
+
return "vi"
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
func openBrowser(url string) error {
|
|
195
|
+
var cmd *exec.Cmd
|
|
196
|
+
|
|
197
|
+
switch runtime.GOOS {
|
|
198
|
+
case "darwin":
|
|
199
|
+
cmd = exec.Command("open", url)
|
|
200
|
+
case "windows":
|
|
201
|
+
cmd = exec.Command("cmd", "/c", "start", url)
|
|
202
|
+
default: // linux, freebsd, etc.
|
|
203
|
+
cmd = exec.Command("xdg-open", url)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return cmd.Start()
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### GOL.3.3.3.5: Handle File Permissions Correctly
|
|
211
|
+
|
|
212
|
+
**Rule**: Use appropriate file permissions that work across platforms.
|
|
213
|
+
|
|
214
|
+
**Severity**: WARNING
|
|
215
|
+
|
|
216
|
+
**✅ Good**:
|
|
217
|
+
```go
|
|
218
|
+
import "os"
|
|
219
|
+
|
|
220
|
+
func createConfigFile(path string) error {
|
|
221
|
+
// 0644 works on Unix, ignored on Windows
|
|
222
|
+
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
|
|
223
|
+
if err != nil {
|
|
224
|
+
return err
|
|
225
|
+
}
|
|
226
|
+
defer f.Close()
|
|
227
|
+
|
|
228
|
+
return nil
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
func createExecutable(path string) error {
|
|
232
|
+
// 0755 makes file executable on Unix
|
|
233
|
+
return os.WriteFile(path, []byte("#!/bin/bash\n"), 0755)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// For sensitive files (like credentials)
|
|
237
|
+
func createSecureFile(path string) error {
|
|
238
|
+
// 0600 = read/write for owner only
|
|
239
|
+
return os.WriteFile(path, []byte("secret"), 0600)
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### GOL.3.3.3.6: Use os.UserHomeDir for Home Directory
|
|
244
|
+
|
|
245
|
+
**Rule**: Use `os.UserHomeDir()` instead of environment variables.
|
|
246
|
+
|
|
247
|
+
**Severity**: ERROR
|
|
248
|
+
|
|
249
|
+
**Rationale**: Works consistently across all platforms.
|
|
250
|
+
|
|
251
|
+
**✅ Good**:
|
|
252
|
+
```go
|
|
253
|
+
func getConfigDir() (string, error) {
|
|
254
|
+
home, err := os.UserHomeDir()
|
|
255
|
+
if err != nil {
|
|
256
|
+
return "", err
|
|
257
|
+
}
|
|
258
|
+
return filepath.Join(home, ".myapp"), nil
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**❌ Bad**:
|
|
263
|
+
```go
|
|
264
|
+
// Doesn't work on Windows
|
|
265
|
+
home := os.Getenv("HOME")
|
|
266
|
+
|
|
267
|
+
// Platform-specific
|
|
268
|
+
home := os.Getenv("USERPROFILE") // Windows only
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### GOL.3.3.3.7: Handle Line Endings
|
|
272
|
+
|
|
273
|
+
**Rule**: Use `bufio.Scanner` or normalize line endings when reading text files.
|
|
274
|
+
|
|
275
|
+
**Severity**: INFO
|
|
276
|
+
|
|
277
|
+
**✅ Good**:
|
|
278
|
+
```go
|
|
279
|
+
func readLines(path string) ([]string, error) {
|
|
280
|
+
f, err := os.Open(path)
|
|
281
|
+
if err != nil {
|
|
282
|
+
return nil, err
|
|
283
|
+
}
|
|
284
|
+
defer f.Close()
|
|
285
|
+
|
|
286
|
+
var lines []string
|
|
287
|
+
scanner := bufio.NewScanner(f)
|
|
288
|
+
// Scanner handles \n, \r\n, and \r automatically
|
|
289
|
+
for scanner.Scan() {
|
|
290
|
+
lines = append(lines, scanner.Text())
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return lines, scanner.Err()
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### GOL.3.3.3.8: Test on Multiple Platforms
|
|
298
|
+
|
|
299
|
+
**Rule**: Test CLI tools on Windows, macOS, and Linux before release.
|
|
300
|
+
|
|
301
|
+
**Severity**: WARNING
|
|
302
|
+
|
|
303
|
+
**✅ Good - GitHub Actions**:
|
|
304
|
+
```yaml
|
|
305
|
+
name: Test
|
|
306
|
+
on: [push, pull_request]
|
|
307
|
+
jobs:
|
|
308
|
+
test:
|
|
309
|
+
strategy:
|
|
310
|
+
matrix:
|
|
311
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
312
|
+
runs-on: ${{ matrix.os }}
|
|
313
|
+
steps:
|
|
314
|
+
- uses: actions/checkout@v2
|
|
315
|
+
- uses: actions/setup-go@v2
|
|
316
|
+
- run: go test ./...
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## References
|
|
320
|
+
|
|
321
|
+
- [Go filepath package](https://pkg.go.dev/path/filepath)
|
|
322
|
+
- [Cross-Platform Go](https://www.digitalocean.com/community/tutorials/building-go-applications-for-different-operating-systems-and-architectures)
|
|
323
|
+
- [Exit Status Codes](https://tldp.org/LDP/abs/html/exitcodes.html)
|
|
324
|
+
|