chore: Go 1.26 modernization #2
66 changed files with 267 additions and 245 deletions
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
|
@ -920,20 +921,16 @@ func (e *Executor) matchesTags(taskTags []string) bool {
|
|||
|
||||
// Check skip tags
|
||||
for _, skip := range e.SkipTags {
|
||||
for _, tt := range taskTags {
|
||||
if skip == tt {
|
||||
return false
|
||||
}
|
||||
if slices.Contains(taskTags, skip) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Check include tags
|
||||
if len(e.Tags) > 0 {
|
||||
for _, tag := range e.Tags {
|
||||
for _, tt := range taskTags {
|
||||
if tag == tt || tag == "all" {
|
||||
return true
|
||||
}
|
||||
if tag == "all" || slices.Contains(taskTags, tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package ansible
|
|||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -178,7 +179,7 @@ func (e *Executor) moduleShell(ctx context.Context, client *SSHClient, args map[
|
|||
cmd = getStringArg(args, "cmd", "")
|
||||
}
|
||||
if cmd == "" {
|
||||
return nil, fmt.Errorf("shell: no command specified")
|
||||
return nil, errors.New("shell: no command specified")
|
||||
}
|
||||
|
||||
// Handle chdir
|
||||
|
|
@ -206,7 +207,7 @@ func (e *Executor) moduleCommand(ctx context.Context, client *SSHClient, args ma
|
|||
cmd = getStringArg(args, "cmd", "")
|
||||
}
|
||||
if cmd == "" {
|
||||
return nil, fmt.Errorf("command: no command specified")
|
||||
return nil, errors.New("command: no command specified")
|
||||
}
|
||||
|
||||
// Handle chdir
|
||||
|
|
@ -231,7 +232,7 @@ func (e *Executor) moduleCommand(ctx context.Context, client *SSHClient, args ma
|
|||
func (e *Executor) moduleRaw(ctx context.Context, client *SSHClient, args map[string]any) (*TaskResult, error) {
|
||||
cmd := getStringArg(args, "_raw_params", "")
|
||||
if cmd == "" {
|
||||
return nil, fmt.Errorf("raw: no command specified")
|
||||
return nil, errors.New("raw: no command specified")
|
||||
}
|
||||
|
||||
stdout, stderr, rc, err := client.Run(ctx, cmd)
|
||||
|
|
@ -250,7 +251,7 @@ func (e *Executor) moduleRaw(ctx context.Context, client *SSHClient, args map[st
|
|||
func (e *Executor) moduleScript(ctx context.Context, client *SSHClient, args map[string]any) (*TaskResult, error) {
|
||||
script := getStringArg(args, "_raw_params", "")
|
||||
if script == "" {
|
||||
return nil, fmt.Errorf("script: no script specified")
|
||||
return nil, errors.New("script: no script specified")
|
||||
}
|
||||
|
||||
// Read local script
|
||||
|
|
@ -278,7 +279,7 @@ func (e *Executor) moduleScript(ctx context.Context, client *SSHClient, args map
|
|||
func (e *Executor) moduleCopy(ctx context.Context, client *SSHClient, args map[string]any, host string, task *Task) (*TaskResult, error) {
|
||||
dest := getStringArg(args, "dest", "")
|
||||
if dest == "" {
|
||||
return nil, fmt.Errorf("copy: dest required")
|
||||
return nil, errors.New("copy: dest required")
|
||||
}
|
||||
|
||||
var content []byte
|
||||
|
|
@ -292,7 +293,7 @@ func (e *Executor) moduleCopy(ctx context.Context, client *SSHClient, args map[s
|
|||
} else if c := getStringArg(args, "content", ""); c != "" {
|
||||
content = []byte(c)
|
||||
} else {
|
||||
return nil, fmt.Errorf("copy: src or content required")
|
||||
return nil, errors.New("copy: src or content required")
|
||||
}
|
||||
|
||||
mode := os.FileMode(0644)
|
||||
|
|
@ -322,7 +323,7 @@ func (e *Executor) moduleTemplate(ctx context.Context, client *SSHClient, args m
|
|||
src := getStringArg(args, "src", "")
|
||||
dest := getStringArg(args, "dest", "")
|
||||
if src == "" || dest == "" {
|
||||
return nil, fmt.Errorf("template: src and dest required")
|
||||
return nil, errors.New("template: src and dest required")
|
||||
}
|
||||
|
||||
// Process template
|
||||
|
|
@ -352,7 +353,7 @@ func (e *Executor) moduleFile(ctx context.Context, client *SSHClient, args map[s
|
|||
path = getStringArg(args, "dest", "")
|
||||
}
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("file: path required")
|
||||
return nil, errors.New("file: path required")
|
||||
}
|
||||
|
||||
state := getStringArg(args, "state", "file")
|
||||
|
|
@ -383,7 +384,7 @@ func (e *Executor) moduleFile(ctx context.Context, client *SSHClient, args map[s
|
|||
case "link":
|
||||
src := getStringArg(args, "src", "")
|
||||
if src == "" {
|
||||
return nil, fmt.Errorf("file: src required for link state")
|
||||
return nil, errors.New("file: src required for link state")
|
||||
}
|
||||
cmd := fmt.Sprintf("ln -sf %q %q", src, path)
|
||||
_, stderr, rc, err := client.Run(ctx, cmd)
|
||||
|
|
@ -420,7 +421,7 @@ func (e *Executor) moduleLineinfile(ctx context.Context, client *SSHClient, args
|
|||
path = getStringArg(args, "dest", "")
|
||||
}
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("lineinfile: path required")
|
||||
return nil, errors.New("lineinfile: path required")
|
||||
}
|
||||
|
||||
line := getStringArg(args, "line", "")
|
||||
|
|
@ -460,7 +461,7 @@ func (e *Executor) moduleLineinfile(ctx context.Context, client *SSHClient, args
|
|||
func (e *Executor) moduleStat(ctx context.Context, client *SSHClient, args map[string]any) (*TaskResult, error) {
|
||||
path := getStringArg(args, "path", "")
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("stat: path required")
|
||||
return nil, errors.New("stat: path required")
|
||||
}
|
||||
|
||||
stat, err := client.Stat(ctx, path)
|
||||
|
|
@ -480,7 +481,7 @@ func (e *Executor) moduleSlurp(ctx context.Context, client *SSHClient, args map[
|
|||
path = getStringArg(args, "src", "")
|
||||
}
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("slurp: path required")
|
||||
return nil, errors.New("slurp: path required")
|
||||
}
|
||||
|
||||
content, err := client.Download(ctx, path)
|
||||
|
|
@ -500,7 +501,7 @@ func (e *Executor) moduleFetch(ctx context.Context, client *SSHClient, args map[
|
|||
src := getStringArg(args, "src", "")
|
||||
dest := getStringArg(args, "dest", "")
|
||||
if src == "" || dest == "" {
|
||||
return nil, fmt.Errorf("fetch: src and dest required")
|
||||
return nil, errors.New("fetch: src and dest required")
|
||||
}
|
||||
|
||||
content, err := client.Download(ctx, src)
|
||||
|
|
@ -524,7 +525,7 @@ func (e *Executor) moduleGetURL(ctx context.Context, client *SSHClient, args map
|
|||
url := getStringArg(args, "url", "")
|
||||
dest := getStringArg(args, "dest", "")
|
||||
if url == "" || dest == "" {
|
||||
return nil, fmt.Errorf("get_url: url and dest required")
|
||||
return nil, errors.New("get_url: url and dest required")
|
||||
}
|
||||
|
||||
// Use curl or wget
|
||||
|
|
@ -591,7 +592,7 @@ func (e *Executor) moduleAptKey(ctx context.Context, client *SSHClient, args map
|
|||
}
|
||||
|
||||
if url == "" {
|
||||
return nil, fmt.Errorf("apt_key: url required")
|
||||
return nil, errors.New("apt_key: url required")
|
||||
}
|
||||
|
||||
var cmd string
|
||||
|
|
@ -615,7 +616,7 @@ func (e *Executor) moduleAptRepository(ctx context.Context, client *SSHClient, a
|
|||
state := getStringArg(args, "state", "present")
|
||||
|
||||
if repo == "" {
|
||||
return nil, fmt.Errorf("apt_repository: repo required")
|
||||
return nil, errors.New("apt_repository: repo required")
|
||||
}
|
||||
|
||||
if filename == "" {
|
||||
|
|
@ -690,7 +691,7 @@ func (e *Executor) moduleService(ctx context.Context, client *SSHClient, args ma
|
|||
enabled := args["enabled"]
|
||||
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("service: name required")
|
||||
return nil, errors.New("service: name required")
|
||||
}
|
||||
|
||||
var cmds []string
|
||||
|
|
@ -742,7 +743,7 @@ func (e *Executor) moduleUser(ctx context.Context, client *SSHClient, args map[s
|
|||
state := getStringArg(args, "state", "present")
|
||||
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("user: name required")
|
||||
return nil, errors.New("user: name required")
|
||||
}
|
||||
|
||||
if state == "absent" {
|
||||
|
|
@ -799,7 +800,7 @@ func (e *Executor) moduleGroup(ctx context.Context, client *SSHClient, args map[
|
|||
state := getStringArg(args, "state", "present")
|
||||
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("group: name required")
|
||||
return nil, errors.New("group: name required")
|
||||
}
|
||||
|
||||
if state == "absent" {
|
||||
|
|
@ -834,7 +835,7 @@ func (e *Executor) moduleURI(ctx context.Context, client *SSHClient, args map[st
|
|||
method := getStringArg(args, "method", "GET")
|
||||
|
||||
if url == "" {
|
||||
return nil, fmt.Errorf("uri: url required")
|
||||
return nil, errors.New("uri: url required")
|
||||
}
|
||||
|
||||
var curlOpts []string
|
||||
|
|
@ -912,7 +913,7 @@ func (e *Executor) moduleFail(args map[string]any) (*TaskResult, error) {
|
|||
func (e *Executor) moduleAssert(args map[string]any, host string) (*TaskResult, error) {
|
||||
that, ok := args["that"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("assert: 'that' required")
|
||||
return nil, errors.New("assert: 'that' required")
|
||||
}
|
||||
|
||||
conditions := normalizeConditions(that)
|
||||
|
|
@ -1013,7 +1014,7 @@ func (e *Executor) moduleGit(ctx context.Context, client *SSHClient, args map[st
|
|||
version := getStringArg(args, "version", "HEAD")
|
||||
|
||||
if repo == "" || dest == "" {
|
||||
return nil, fmt.Errorf("git: repo and dest required")
|
||||
return nil, errors.New("git: repo and dest required")
|
||||
}
|
||||
|
||||
// Check if dest exists
|
||||
|
|
@ -1042,7 +1043,7 @@ func (e *Executor) moduleUnarchive(ctx context.Context, client *SSHClient, args
|
|||
remote := getBoolArg(args, "remote_src", false)
|
||||
|
||||
if src == "" || dest == "" {
|
||||
return nil, fmt.Errorf("unarchive: src and dest required")
|
||||
return nil, errors.New("unarchive: src and dest required")
|
||||
}
|
||||
|
||||
// Create dest directory (best-effort)
|
||||
|
|
@ -1117,7 +1118,7 @@ func getBoolArg(args map[string]any, key string, def bool) bool {
|
|||
func (e *Executor) moduleHostname(ctx context.Context, client *SSHClient, args map[string]any) (*TaskResult, error) {
|
||||
name := getStringArg(args, "name", "")
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("hostname: name required")
|
||||
return nil, errors.New("hostname: name required")
|
||||
}
|
||||
|
||||
// Set hostname
|
||||
|
|
@ -1139,7 +1140,7 @@ func (e *Executor) moduleSysctl(ctx context.Context, client *SSHClient, args map
|
|||
state := getStringArg(args, "state", "present")
|
||||
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("sysctl: name required")
|
||||
return nil, errors.New("sysctl: name required")
|
||||
}
|
||||
|
||||
if state == "absent" {
|
||||
|
|
@ -1209,7 +1210,7 @@ func (e *Executor) moduleBlockinfile(ctx context.Context, client *SSHClient, arg
|
|||
path = getStringArg(args, "dest", "")
|
||||
}
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("blockinfile: path required")
|
||||
return nil, errors.New("blockinfile: path required")
|
||||
}
|
||||
|
||||
block := getStringArg(args, "block", "")
|
||||
|
|
@ -1357,7 +1358,7 @@ func (e *Executor) moduleAuthorizedKey(ctx context.Context, client *SSHClient, a
|
|||
state := getStringArg(args, "state", "present")
|
||||
|
||||
if user == "" || key == "" {
|
||||
return nil, fmt.Errorf("authorized_key: user and key required")
|
||||
return nil, errors.New("authorized_key: user and key required")
|
||||
}
|
||||
|
||||
// Get user's home directory
|
||||
|
|
@ -1407,7 +1408,7 @@ func (e *Executor) moduleDockerCompose(ctx context.Context, client *SSHClient, a
|
|||
state := getStringArg(args, "state", "present")
|
||||
|
||||
if projectSrc == "" {
|
||||
return nil, fmt.Errorf("docker_compose: project_src required")
|
||||
return nil, errors.New("docker_compose: project_src required")
|
||||
}
|
||||
|
||||
var cmd string
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ import (
|
|||
"archive/zip"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Snider/Borg/pkg/compress"
|
||||
io_interface "forge.lthn.ai/core/go/pkg/io"
|
||||
"github.com/Snider/Borg/pkg/compress"
|
||||
)
|
||||
|
||||
// ArchiveFormat specifies the compression format for archives.
|
||||
|
|
@ -48,7 +49,7 @@ func ArchiveXZ(fs io_interface.Medium, artifact Artifact) (Artifact, error) {
|
|||
// Returns a new Artifact with Path pointing to the archive.
|
||||
func ArchiveWithFormat(fs io_interface.Medium, artifact Artifact, format ArchiveFormat) (Artifact, error) {
|
||||
if artifact.Path == "" {
|
||||
return Artifact{}, fmt.Errorf("build.Archive: artifact path is empty")
|
||||
return Artifact{}, errors.New("build.Archive: artifact path is empty")
|
||||
}
|
||||
|
||||
// Verify the source file exists
|
||||
|
|
@ -57,7 +58,7 @@ func ArchiveWithFormat(fs io_interface.Medium, artifact Artifact, format Archive
|
|||
return Artifact{}, fmt.Errorf("build.Archive: source file not found: %w", err)
|
||||
}
|
||||
if info.IsDir() {
|
||||
return Artifact{}, fmt.Errorf("build.Archive: source path is a directory, expected file")
|
||||
return Artifact{}, errors.New("build.Archive: source path is a directory, expected file")
|
||||
}
|
||||
|
||||
// Determine archive type based on OS and format
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ func runProjectBuild(ctx context.Context, buildType string, ciMode bool, targets
|
|||
return fmt.Errorf("%s: %w", i18n.T("common.error.failed", map[string]any{"Action": "detect project type"}), err)
|
||||
}
|
||||
if projectType == "" {
|
||||
return fmt.Errorf("%s", i18n.T("cmd.build.error.no_project_type", map[string]interface{}{"Dir": projectDir}))
|
||||
return fmt.Errorf("%s", i18n.T("cmd.build.error.no_project_type", map[string]any{"Dir": projectDir}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ func runProjectBuild(ctx context.Context, buildType string, ciMode bool, targets
|
|||
}
|
||||
|
||||
if verbose && !ciMode {
|
||||
fmt.Printf("%s %s\n", buildSuccessStyle.Render(i18n.T("common.label.success")), i18n.T("cmd.build.built_artifacts", map[string]interface{}{"Count": len(artifacts)}))
|
||||
fmt.Printf("%s %s\n", buildSuccessStyle.Render(i18n.T("common.label.success")), i18n.T("cmd.build.built_artifacts", map[string]any{"Count": len(artifacts)}))
|
||||
fmt.Println()
|
||||
for _, artifact := range artifacts {
|
||||
relPath, err := filepath.Rel(projectDir, artifact.Path)
|
||||
|
|
@ -260,7 +260,7 @@ func runProjectBuild(ctx context.Context, buildType string, ciMode bool, targets
|
|||
// Minimal output: just success with artifact count
|
||||
fmt.Printf("%s %s %s\n",
|
||||
buildSuccessStyle.Render(i18n.T("common.label.success")),
|
||||
i18n.T("cmd.build.built_artifacts", map[string]interface{}{"Count": len(artifacts)}),
|
||||
i18n.T("cmd.build.built_artifacts", map[string]any{"Count": len(artifacts)}),
|
||||
buildDimStyle.Render(fmt.Sprintf("(%s)", outputDir)),
|
||||
)
|
||||
}
|
||||
|
|
@ -342,7 +342,7 @@ func parseTargets(targetsFlag string) ([]build.Target, error) {
|
|||
|
||||
osArch := strings.Split(part, "/")
|
||||
if len(osArch) != 2 {
|
||||
return nil, fmt.Errorf("%s", i18n.T("cmd.build.error.invalid_target", map[string]interface{}{"Target": part}))
|
||||
return nil, fmt.Errorf("%s", i18n.T("cmd.build.error.invalid_target", map[string]any{"Target": part}))
|
||||
}
|
||||
|
||||
targets = append(targets, build.Target{
|
||||
|
|
|
|||
|
|
@ -147,14 +147,14 @@ func findManifestURL(htmlContent, baseURL string) (string, error) {
|
|||
}
|
||||
|
||||
// fetchManifest downloads and parses a PWA manifest.
|
||||
func fetchManifest(manifestURL string) (map[string]interface{}, error) {
|
||||
func fetchManifest(manifestURL string) (map[string]any, error) {
|
||||
resp, err := http.Get(manifestURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
var manifest map[string]interface{}
|
||||
var manifest map[string]any
|
||||
if err := json.NewDecoder(resp.Body).Decode(&manifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ func fetchManifest(manifestURL string) (map[string]interface{}, error) {
|
|||
}
|
||||
|
||||
// collectAssets extracts asset URLs from a PWA manifest.
|
||||
func collectAssets(manifest map[string]interface{}, manifestURL string) []string {
|
||||
func collectAssets(manifest map[string]any, manifestURL string) []string {
|
||||
var assets []string
|
||||
base, _ := url.Parse(manifestURL)
|
||||
|
||||
|
|
@ -174,9 +174,9 @@ func collectAssets(manifest map[string]interface{}, manifestURL string) []string
|
|||
}
|
||||
|
||||
// Add icons
|
||||
if icons, ok := manifest["icons"].([]interface{}); ok {
|
||||
if icons, ok := manifest["icons"].([]any); ok {
|
||||
for _, icon := range icons {
|
||||
if iconMap, ok := icon.(map[string]interface{}); ok {
|
||||
if iconMap, ok := icon.(map[string]any); ok {
|
||||
if src, ok := iconMap["src"].(string); ok {
|
||||
if resolved, err := base.Parse(src); err == nil {
|
||||
assets = append(assets, resolved.String())
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package builders
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -38,7 +39,7 @@ func (b *CPPBuilder) Detect(fs io.Medium, dir string) (bool, error) {
|
|||
// Cross-compilation is handled via Conan profiles specified in .core/build.yaml.
|
||||
func (b *CPPBuilder) Build(ctx context.Context, cfg *build.Config, targets []build.Target) ([]build.Artifact, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("builders.CPPBuilder.Build: config is nil")
|
||||
return nil, errors.New("builders.CPPBuilder.Build: config is nil")
|
||||
}
|
||||
|
||||
// Validate make is available
|
||||
|
|
@ -244,7 +245,7 @@ func (b *CPPBuilder) targetToProfile(target build.Target) string {
|
|||
// validateMake checks if make is available.
|
||||
func (b *CPPBuilder) validateMake() error {
|
||||
if _, err := exec.LookPath("make"); err != nil {
|
||||
return fmt.Errorf("cpp: make not found. Install build-essential (Linux) or Xcode Command Line Tools (macOS)")
|
||||
return errors.New("cpp: make not found. Install build-essential (Linux) or Xcode Command Line Tools (macOS)")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package builders
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -186,7 +187,7 @@ func (b *DockerBuilder) Build(ctx context.Context, cfg *build.Config, targets []
|
|||
func (b *DockerBuilder) validateDockerCli() error {
|
||||
cmd := exec.Command("docker", "--version")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("docker: docker CLI not found. Install it from https://docs.docker.com/get-docker/")
|
||||
return errors.New("docker: docker CLI not found. Install it from https://docs.docker.com/get-docker/")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -196,7 +197,7 @@ func (b *DockerBuilder) ensureBuildx(ctx context.Context) error {
|
|||
// Check if buildx is available
|
||||
cmd := exec.CommandContext(ctx, "docker", "buildx", "version")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("docker: buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/")
|
||||
return errors.New("docker: buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/")
|
||||
}
|
||||
|
||||
// Check if we have a builder, create one if not
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package builders
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -37,11 +38,11 @@ func (b *GoBuilder) Detect(fs io.Medium, dir string) (bool, error) {
|
|||
// applies ldflags and trimpath, and runs go build.
|
||||
func (b *GoBuilder) Build(ctx context.Context, cfg *build.Config, targets []build.Target) ([]build.Artifact, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("builders.GoBuilder.Build: config is nil")
|
||||
return nil, errors.New("builders.GoBuilder.Build: config is nil")
|
||||
}
|
||||
|
||||
if len(targets) == 0 {
|
||||
return nil, fmt.Errorf("builders.GoBuilder.Build: no targets specified")
|
||||
return nil, errors.New("builders.GoBuilder.Build: no targets specified")
|
||||
}
|
||||
|
||||
// Ensure output directory exists
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package builders
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -78,7 +79,7 @@ func (b *LinuxKitBuilder) Build(ctx context.Context, cfg *build.Config, targets
|
|||
}
|
||||
|
||||
if configPath == "" {
|
||||
return nil, fmt.Errorf("linuxkit.Build: no LinuxKit config file found. Specify with --config or create linuxkit.yml")
|
||||
return nil, errors.New("linuxkit.Build: no LinuxKit config file found. Specify with --config or create linuxkit.yml")
|
||||
}
|
||||
|
||||
// Validate config file exists
|
||||
|
|
@ -266,5 +267,5 @@ func (b *LinuxKitBuilder) validateLinuxKitCli() error {
|
|||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("linuxkit: linuxkit CLI not found. Install with: brew install linuxkit (macOS) or see https://github.com/linuxkit/linuxkit")
|
||||
return errors.New("linuxkit: linuxkit CLI not found. Install with: brew install linuxkit (macOS) or see https://github.com/linuxkit/linuxkit")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package builders
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -271,5 +272,5 @@ func (b *TaskfileBuilder) validateTaskCli() error {
|
|||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("taskfile: task CLI not found. Install with: brew install go-task (macOS), go install github.com/go-task/task/v3/cmd/task@latest, or see https://taskfile.dev/installation/")
|
||||
return errors.New("taskfile: task CLI not found. Install with: brew install go-task (macOS), go install github.com/go-task/task/v3/cmd/task@latest, or see https://taskfile.dev/installation/")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package builders
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
@ -37,11 +38,11 @@ func (b *WailsBuilder) Detect(fs io.Medium, dir string) (bool, error) {
|
|||
// - Wails v2: Uses 'wails build' command
|
||||
func (b *WailsBuilder) Build(ctx context.Context, cfg *build.Config, targets []build.Target) ([]build.Artifact, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("builders.WailsBuilder.Build: config is nil")
|
||||
return nil, errors.New("builders.WailsBuilder.Build: config is nil")
|
||||
}
|
||||
|
||||
if len(targets) == 0 {
|
||||
return nil, fmt.Errorf("builders.WailsBuilder.Build: no targets specified")
|
||||
return nil, errors.New("builders.WailsBuilder.Build: no targets specified")
|
||||
}
|
||||
|
||||
// Detect Wails version
|
||||
|
|
@ -53,7 +54,7 @@ func (b *WailsBuilder) Build(ctx context.Context, cfg *build.Config, targets []b
|
|||
if detected, _ := taskBuilder.Detect(cfg.FS, cfg.ProjectDir); detected {
|
||||
return taskBuilder.Build(ctx, cfg, targets)
|
||||
}
|
||||
return nil, fmt.Errorf("wails v3 projects require a Taskfile for building")
|
||||
return nil, errors.New("wails v3 projects require a Taskfile for building")
|
||||
}
|
||||
|
||||
// Wails v2 strategy: Use 'wails build'
|
||||
|
|
|
|||
|
|
@ -4,19 +4,21 @@ package build
|
|||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
||||
"strings"
|
||||
|
||||
io_interface "forge.lthn.ai/core/go/pkg/io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Checksum computes SHA256 for an artifact and returns the artifact with the Checksum field filled.
|
||||
func Checksum(fs io_interface.Medium, artifact Artifact) (Artifact, error) {
|
||||
if artifact.Path == "" {
|
||||
return Artifact{}, fmt.Errorf("build.Checksum: artifact path is empty")
|
||||
return Artifact{}, errors.New("build.Checksum: artifact path is empty")
|
||||
}
|
||||
|
||||
// Open the file
|
||||
|
|
@ -84,7 +86,7 @@ func WriteChecksumFile(fs io_interface.Medium, artifacts []Artifact, path string
|
|||
}
|
||||
|
||||
// Sort lines for consistent output
|
||||
sort.Strings(lines)
|
||||
slices.Sort(lines)
|
||||
|
||||
content := strings.Join(lines, "\n") + "\n"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package signing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
|
@ -42,7 +43,7 @@ func (s *MacOSSigner) Available() bool {
|
|||
// Sign codesigns a binary with hardened runtime.
|
||||
func (s *MacOSSigner) Sign(ctx context.Context, fs io.Medium, binary string) error {
|
||||
if !s.Available() {
|
||||
return fmt.Errorf("codesign.Sign: codesign not available")
|
||||
return errors.New("codesign.Sign: codesign not available")
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, "codesign",
|
||||
|
|
@ -65,7 +66,7 @@ func (s *MacOSSigner) Sign(ctx context.Context, fs io.Medium, binary string) err
|
|||
// This blocks until Apple responds (typically 1-5 minutes).
|
||||
func (s *MacOSSigner) Notarize(ctx context.Context, fs io.Medium, binary string) error {
|
||||
if s.config.AppleID == "" || s.config.TeamID == "" || s.config.AppPassword == "" {
|
||||
return fmt.Errorf("codesign.Notarize: missing Apple credentials (apple_id, team_id, app_password)")
|
||||
return errors.New("codesign.Notarize: missing Apple credentials (apple_id, team_id, app_password)")
|
||||
}
|
||||
|
||||
// Create ZIP for submission
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package signing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
|
|
@ -39,7 +40,7 @@ func (s *GPGSigner) Available() bool {
|
|||
// For file.txt, creates file.txt.asc
|
||||
func (s *GPGSigner) Sign(ctx context.Context, fs io.Medium, file string) error {
|
||||
if !s.Available() {
|
||||
return fmt.Errorf("gpg.Sign: gpg not available or key not configured")
|
||||
return errors.New("gpg.Sign: gpg not available or key not configured")
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, "gpg",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package signing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ func NotarizeBinaries(ctx context.Context, fs io.Medium, cfg SignConfig, artifac
|
|||
|
||||
signer := NewMacOSSigner(cfg.MacOS)
|
||||
if !signer.Available() {
|
||||
return fmt.Errorf("notarization requested but codesign not available")
|
||||
return errors.New("notarization requested but codesign not available")
|
||||
}
|
||||
|
||||
for _, artifact := range artifacts {
|
||||
|
|
|
|||
|
|
@ -203,19 +203,19 @@ func runApply() error {
|
|||
cli.Blank()
|
||||
cli.Print("%s: ", i18n.T("cmd.dev.apply.summary"))
|
||||
if succeeded > 0 {
|
||||
cli.Print("%s", successStyle.Render(i18n.T("common.count.succeeded", map[string]interface{}{"Count": succeeded})))
|
||||
cli.Print("%s", successStyle.Render(i18n.T("common.count.succeeded", map[string]any{"Count": succeeded})))
|
||||
}
|
||||
if skipped > 0 {
|
||||
if succeeded > 0 {
|
||||
cli.Print(", ")
|
||||
}
|
||||
cli.Print("%s", dimStyle.Render(i18n.T("common.count.skipped", map[string]interface{}{"Count": skipped})))
|
||||
cli.Print("%s", dimStyle.Render(i18n.T("common.count.skipped", map[string]any{"Count": skipped})))
|
||||
}
|
||||
if failed > 0 {
|
||||
if succeeded > 0 || skipped > 0 {
|
||||
cli.Print(", ")
|
||||
}
|
||||
cli.Print("%s", errorStyle.Render(i18n.T("common.count.failed", map[string]interface{}{"Count": failed})))
|
||||
cli.Print("%s", errorStyle.Render(i18n.T("common.count.failed", map[string]any{"Count": failed})))
|
||||
}
|
||||
cli.Blank()
|
||||
|
||||
|
|
|
|||
|
|
@ -146,18 +146,18 @@ func runCI(registryPath string, branch string, failedOnly bool) error {
|
|||
|
||||
// Print summary
|
||||
cli.Blank()
|
||||
cli.Print("%s", i18n.T("cmd.dev.ci.repos_checked", map[string]interface{}{"Count": len(repoList)}))
|
||||
cli.Print("%s", i18n.T("cmd.dev.ci.repos_checked", map[string]any{"Count": len(repoList)}))
|
||||
if success > 0 {
|
||||
cli.Print(" * %s", ciSuccessStyle.Render(i18n.T("cmd.dev.ci.passing", map[string]interface{}{"Count": success})))
|
||||
cli.Print(" * %s", ciSuccessStyle.Render(i18n.T("cmd.dev.ci.passing", map[string]any{"Count": success})))
|
||||
}
|
||||
if failed > 0 {
|
||||
cli.Print(" * %s", ciFailureStyle.Render(i18n.T("cmd.dev.ci.failing", map[string]interface{}{"Count": failed})))
|
||||
cli.Print(" * %s", ciFailureStyle.Render(i18n.T("cmd.dev.ci.failing", map[string]any{"Count": failed})))
|
||||
}
|
||||
if pending > 0 {
|
||||
cli.Print(" * %s", ciPendingStyle.Render(i18n.T("common.count.pending", map[string]interface{}{"Count": pending})))
|
||||
cli.Print(" * %s", ciPendingStyle.Render(i18n.T("common.count.pending", map[string]any{"Count": pending})))
|
||||
}
|
||||
if len(noCI) > 0 {
|
||||
cli.Print(" * %s", ciSkippedStyle.Render(i18n.T("cmd.dev.ci.no_ci", map[string]interface{}{"Count": len(noCI)})))
|
||||
cli.Print(" * %s", ciSkippedStyle.Render(i18n.T("cmd.dev.ci.no_ci", map[string]any{"Count": len(noCI)})))
|
||||
}
|
||||
cli.Blank()
|
||||
cli.Blank()
|
||||
|
|
|
|||
|
|
@ -86,17 +86,17 @@ func runCommit(registryPath string, all bool) error {
|
|||
}
|
||||
|
||||
// Show dirty repos
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.repos_with_changes", map[string]interface{}{"Count": len(dirtyRepos)}))
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.repos_with_changes", map[string]any{"Count": len(dirtyRepos)}))
|
||||
for _, s := range dirtyRepos {
|
||||
cli.Print(" %s: ", repoNameStyle.Render(s.Name))
|
||||
if s.Modified > 0 {
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.modified", map[string]interface{}{"Count": s.Modified})))
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.modified", map[string]any{"Count": s.Modified})))
|
||||
}
|
||||
if s.Untracked > 0 {
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.untracked", map[string]interface{}{"Count": s.Untracked})))
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.untracked", map[string]any{"Count": s.Untracked})))
|
||||
}
|
||||
if s.Staged > 0 {
|
||||
cli.Print("%s ", aheadStyle.Render(i18n.T("cmd.dev.staged", map[string]interface{}{"Count": s.Staged})))
|
||||
cli.Print("%s ", aheadStyle.Render(i18n.T("cmd.dev.staged", map[string]any{"Count": s.Staged})))
|
||||
}
|
||||
cli.Blank()
|
||||
}
|
||||
|
|
@ -128,9 +128,9 @@ func runCommit(registryPath string, all bool) error {
|
|||
}
|
||||
|
||||
// Summary
|
||||
cli.Print("%s", successStyle.Render(i18n.T("cmd.dev.done_succeeded", map[string]interface{}{"Count": succeeded})))
|
||||
cli.Print("%s", successStyle.Render(i18n.T("cmd.dev.done_succeeded", map[string]any{"Count": succeeded})))
|
||||
if failed > 0 {
|
||||
cli.Print(", %s", errorStyle.Render(i18n.T("common.count.failed", map[string]interface{}{"Count": failed})))
|
||||
cli.Print(", %s", errorStyle.Render(i18n.T("common.count.failed", map[string]any{"Count": failed})))
|
||||
}
|
||||
cli.Blank()
|
||||
|
||||
|
|
@ -170,13 +170,13 @@ func runCommitSingleRepo(ctx context.Context, repoPath string, all bool) error {
|
|||
// Show status
|
||||
cli.Print("%s: ", repoNameStyle.Render(s.Name))
|
||||
if s.Modified > 0 {
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.modified", map[string]interface{}{"Count": s.Modified})))
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.modified", map[string]any{"Count": s.Modified})))
|
||||
}
|
||||
if s.Untracked > 0 {
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.untracked", map[string]interface{}{"Count": s.Untracked})))
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.untracked", map[string]any{"Count": s.Untracked})))
|
||||
}
|
||||
if s.Staged > 0 {
|
||||
cli.Print("%s ", aheadStyle.Render(i18n.T("cmd.dev.staged", map[string]interface{}{"Count": s.Staged})))
|
||||
cli.Print("%s ", aheadStyle.Render(i18n.T("cmd.dev.staged", map[string]any{"Count": s.Staged})))
|
||||
}
|
||||
cli.Blank()
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func runFileSync(source string) error {
|
|||
// Let's stick to os.Stat for source properties finding as typically allowed for CLI args.
|
||||
|
||||
if err != nil {
|
||||
return log.E("dev.sync", i18n.T("cmd.dev.file_sync.error.source_not_found", map[string]interface{}{"Path": source}), err)
|
||||
return log.E("dev.sync", i18n.T("cmd.dev.file_sync.error.source_not_found", map[string]any{"Path": source}), err)
|
||||
}
|
||||
|
||||
// Find target repos
|
||||
|
|
@ -185,19 +185,19 @@ func runFileSync(source string) error {
|
|||
cli.Blank()
|
||||
cli.Print("%s: ", i18n.T("cmd.dev.file_sync.summary"))
|
||||
if succeeded > 0 {
|
||||
cli.Print("%s", successStyle.Render(i18n.T("common.count.succeeded", map[string]interface{}{"Count": succeeded})))
|
||||
cli.Print("%s", successStyle.Render(i18n.T("common.count.succeeded", map[string]any{"Count": succeeded})))
|
||||
}
|
||||
if skipped > 0 {
|
||||
if succeeded > 0 {
|
||||
cli.Print(", ")
|
||||
}
|
||||
cli.Print("%s", dimStyle.Render(i18n.T("common.count.skipped", map[string]interface{}{"Count": skipped})))
|
||||
cli.Print("%s", dimStyle.Render(i18n.T("common.count.skipped", map[string]any{"Count": skipped})))
|
||||
}
|
||||
if failed > 0 {
|
||||
if succeeded > 0 || skipped > 0 {
|
||||
cli.Print(", ")
|
||||
}
|
||||
cli.Print("%s", errorStyle.Render(i18n.T("common.count.failed", map[string]interface{}{"Count": failed})))
|
||||
cli.Print("%s", errorStyle.Render(i18n.T("common.count.failed", map[string]any{"Count": failed})))
|
||||
}
|
||||
cli.Blank()
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ func formatRepoList(reposList []string) string {
|
|||
if len(reposList) <= 5 {
|
||||
return joinRepos(reposList)
|
||||
}
|
||||
return joinRepos(reposList[:5]) + " " + i18n.T("cmd.dev.health.more", map[string]interface{}{"Count": len(reposList) - 5})
|
||||
return joinRepos(reposList[:5]) + " " + i18n.T("cmd.dev.health.more", map[string]any{"Count": len(reposList) - 5})
|
||||
}
|
||||
|
||||
func joinRepos(reposList []string) string {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dev
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"slices"
|
||||
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
|
|
@ -62,7 +62,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
// Check repo exists
|
||||
repo, exists := reg.Get(repoName)
|
||||
if !exists {
|
||||
return errors.New(i18n.T("error.repo_not_found", map[string]interface{}{"Name": repoName}))
|
||||
return errors.New(i18n.T("error.repo_not_found", map[string]any{"Name": repoName}))
|
||||
}
|
||||
|
||||
// Build reverse dependency graph
|
||||
|
|
@ -86,8 +86,8 @@ func runImpact(registryPath string, repoName string) error {
|
|||
}
|
||||
|
||||
// Sort for consistent output
|
||||
sort.Strings(direct)
|
||||
sort.Strings(indirect)
|
||||
slices.Sort(direct)
|
||||
slices.Sort(indirect)
|
||||
|
||||
// Print results
|
||||
cli.Blank()
|
||||
|
|
@ -98,7 +98,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
cli.Blank()
|
||||
|
||||
if len(allAffected) == 0 {
|
||||
cli.Print("%s %s\n", impactSafeStyle.Render("v"), i18n.T("cmd.dev.impact.no_dependents", map[string]interface{}{"Name": repoName}))
|
||||
cli.Print("%s %s\n", impactSafeStyle.Render("v"), i18n.T("cmd.dev.impact.no_dependents", map[string]any{"Name": repoName}))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
if len(direct) > 0 {
|
||||
cli.Print("%s %s\n",
|
||||
impactDirectStyle.Render("*"),
|
||||
i18n.T("cmd.dev.impact.direct_dependents", map[string]interface{}{"Count": len(direct)}),
|
||||
i18n.T("cmd.dev.impact.direct_dependents", map[string]any{"Count": len(direct)}),
|
||||
)
|
||||
for _, d := range direct {
|
||||
r, _ := reg.Get(d)
|
||||
|
|
@ -123,7 +123,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
if len(indirect) > 0 {
|
||||
cli.Print("%s %s\n",
|
||||
impactIndirectStyle.Render("o"),
|
||||
i18n.T("cmd.dev.impact.transitive_dependents", map[string]interface{}{"Count": len(indirect)}),
|
||||
i18n.T("cmd.dev.impact.transitive_dependents", map[string]any{"Count": len(indirect)}),
|
||||
)
|
||||
for _, d := range indirect {
|
||||
r, _ := reg.Get(d)
|
||||
|
|
@ -139,7 +139,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
// Summary
|
||||
cli.Print("%s %s\n",
|
||||
dimStyle.Render(i18n.Label("summary")),
|
||||
i18n.T("cmd.dev.impact.changes_affect", map[string]interface{}{
|
||||
i18n.T("cmd.dev.impact.changes_affect", map[string]any{
|
||||
"Repo": repoNameStyle.Render(repoName),
|
||||
"Affected": len(allAffected),
|
||||
"Total": len(reg.Repos) - 1,
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ func runIssues(registryPath string, limit int, assignee string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.issues.open_issues", map[string]interface{}{"Count": len(allIssues)}))
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.issues.open_issues", map[string]any{"Count": len(allIssues)}))
|
||||
|
||||
for _, issue := range allIssues {
|
||||
printIssue(issue)
|
||||
|
|
|
|||
|
|
@ -81,13 +81,13 @@ func runPull(registryPath string, all bool) error {
|
|||
|
||||
// Show what we're pulling
|
||||
if all {
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.pull.pulling_repos", map[string]interface{}{"Count": len(toPull)}))
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.pull.pulling_repos", map[string]any{"Count": len(toPull)}))
|
||||
} else {
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.pull.repos_behind", map[string]interface{}{"Count": len(toPull)}))
|
||||
cli.Print("\n%s\n\n", i18n.T("cmd.dev.pull.repos_behind", map[string]any{"Count": len(toPull)}))
|
||||
for _, s := range toPull {
|
||||
cli.Print(" %s: %s\n",
|
||||
repoNameStyle.Render(s.Name),
|
||||
dimStyle.Render(i18n.T("cmd.dev.pull.commits_behind", map[string]interface{}{"Count": s.Behind})),
|
||||
dimStyle.Render(i18n.T("cmd.dev.pull.commits_behind", map[string]any{"Count": s.Behind})),
|
||||
)
|
||||
}
|
||||
cli.Blank()
|
||||
|
|
@ -110,9 +110,9 @@ func runPull(registryPath string, all bool) error {
|
|||
|
||||
// Summary
|
||||
cli.Blank()
|
||||
cli.Print("%s", successStyle.Render(i18n.T("cmd.dev.pull.done_pulled", map[string]interface{}{"Count": succeeded})))
|
||||
cli.Print("%s", successStyle.Render(i18n.T("cmd.dev.pull.done_pulled", map[string]any{"Count": succeeded})))
|
||||
if failed > 0 {
|
||||
cli.Print(", %s", errorStyle.Render(i18n.T("common.count.failed", map[string]interface{}{"Count": failed})))
|
||||
cli.Print(", %s", errorStyle.Render(i18n.T("common.count.failed", map[string]any{"Count": failed})))
|
||||
}
|
||||
cli.Blank()
|
||||
|
||||
|
|
|
|||
|
|
@ -84,12 +84,12 @@ func runPush(registryPath string, force bool) error {
|
|||
}
|
||||
|
||||
// Show repos to push
|
||||
cli.Print("\n%s\n\n", i18n.T("common.count.repos_unpushed", map[string]interface{}{"Count": len(aheadRepos)}))
|
||||
cli.Print("\n%s\n\n", i18n.T("common.count.repos_unpushed", map[string]any{"Count": len(aheadRepos)}))
|
||||
totalCommits := 0
|
||||
for _, s := range aheadRepos {
|
||||
cli.Print(" %s: %s\n",
|
||||
repoNameStyle.Render(s.Name),
|
||||
aheadStyle.Render(i18n.T("common.count.commits", map[string]interface{}{"Count": s.Ahead})),
|
||||
aheadStyle.Render(i18n.T("common.count.commits", map[string]any{"Count": s.Ahead})),
|
||||
)
|
||||
totalCommits += s.Ahead
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ func runPush(registryPath string, force bool) error {
|
|||
// Confirm unless --force
|
||||
if !force {
|
||||
cli.Blank()
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]interface{}{"Commits": totalCommits, "Repos": len(aheadRepos)})) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]any{"Commits": totalCommits, "Repos": len(aheadRepos)})) {
|
||||
cli.Text(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -158,9 +158,9 @@ func runPush(registryPath string, force bool) error {
|
|||
|
||||
// Summary
|
||||
cli.Blank()
|
||||
cli.Print("%s", successStyle.Render(i18n.T("cmd.dev.push.done_pushed", map[string]interface{}{"Count": succeeded})))
|
||||
cli.Print("%s", successStyle.Render(i18n.T("cmd.dev.push.done_pushed", map[string]any{"Count": succeeded})))
|
||||
if failed > 0 {
|
||||
cli.Print(", %s", errorStyle.Render(i18n.T("common.count.failed", map[string]interface{}{"Count": failed})))
|
||||
cli.Print(", %s", errorStyle.Render(i18n.T("common.count.failed", map[string]any{"Count": failed})))
|
||||
}
|
||||
cli.Blank()
|
||||
|
||||
|
|
@ -191,13 +191,13 @@ func runPushSingleRepo(ctx context.Context, repoPath string, force bool) error {
|
|||
if s.IsDirty() {
|
||||
cli.Print("%s: ", repoNameStyle.Render(s.Name))
|
||||
if s.Modified > 0 {
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.modified", map[string]interface{}{"Count": s.Modified})))
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.modified", map[string]any{"Count": s.Modified})))
|
||||
}
|
||||
if s.Untracked > 0 {
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.untracked", map[string]interface{}{"Count": s.Untracked})))
|
||||
cli.Print("%s ", dirtyStyle.Render(i18n.T("cmd.dev.untracked", map[string]any{"Count": s.Untracked})))
|
||||
}
|
||||
if s.Staged > 0 {
|
||||
cli.Print("%s ", aheadStyle.Render(i18n.T("cmd.dev.staged", map[string]interface{}{"Count": s.Staged})))
|
||||
cli.Print("%s ", aheadStyle.Render(i18n.T("cmd.dev.staged", map[string]any{"Count": s.Staged})))
|
||||
}
|
||||
cli.Blank()
|
||||
cli.Blank()
|
||||
|
|
@ -230,12 +230,12 @@ func runPushSingleRepo(ctx context.Context, repoPath string, force bool) error {
|
|||
|
||||
// Show commits to push
|
||||
cli.Print("%s: %s\n", repoNameStyle.Render(s.Name),
|
||||
aheadStyle.Render(i18n.T("common.count.commits", map[string]interface{}{"Count": s.Ahead})))
|
||||
aheadStyle.Render(i18n.T("common.count.commits", map[string]any{"Count": s.Ahead})))
|
||||
|
||||
// Confirm unless --force
|
||||
if !force {
|
||||
cli.Blank()
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]interface{}{"Commits": s.Ahead, "Repos": 1})) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]any{"Commits": s.Ahead, "Repos": 1})) {
|
||||
cli.Text(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,15 +144,15 @@ func runReviews(registryPath string, author string, showAll bool) error {
|
|||
}
|
||||
|
||||
cli.Blank()
|
||||
cli.Print("%s", i18n.T("cmd.dev.reviews.open_prs", map[string]interface{}{"Count": len(allPRs)}))
|
||||
cli.Print("%s", i18n.T("cmd.dev.reviews.open_prs", map[string]any{"Count": len(allPRs)}))
|
||||
if pending > 0 {
|
||||
cli.Print(" * %s", prPendingStyle.Render(i18n.T("common.count.pending", map[string]interface{}{"Count": pending})))
|
||||
cli.Print(" * %s", prPendingStyle.Render(i18n.T("common.count.pending", map[string]any{"Count": pending})))
|
||||
}
|
||||
if approved > 0 {
|
||||
cli.Print(" * %s", prApprovedStyle.Render(i18n.T("cmd.dev.reviews.approved", map[string]interface{}{"Count": approved})))
|
||||
cli.Print(" * %s", prApprovedStyle.Render(i18n.T("cmd.dev.reviews.approved", map[string]any{"Count": approved})))
|
||||
}
|
||||
if changesRequested > 0 {
|
||||
cli.Print(" * %s", prChangesStyle.Render(i18n.T("cmd.dev.reviews.changes_requested", map[string]interface{}{"Count": changesRequested})))
|
||||
cli.Print(" * %s", prChangesStyle.Render(i18n.T("cmd.dev.reviews.changes_requested", map[string]any{"Count": changesRequested})))
|
||||
}
|
||||
cli.Blank()
|
||||
cli.Blank()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func runVMInstall() error {
|
|||
if d.IsInstalled() {
|
||||
cli.Text(successStyle.Render(i18n.T("cmd.dev.vm.already_installed")))
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.check_updates", map[string]interface{}{"Command": dimStyle.Render("core dev update")}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.check_updates", map[string]any{"Command": dimStyle.Render("core dev update")}))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -80,9 +80,9 @@ func runVMInstall() error {
|
|||
|
||||
elapsed := time.Since(start).Round(time.Second)
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.installed_in", map[string]interface{}{"Duration": elapsed}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.installed_in", map[string]any{"Duration": elapsed}))
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.start_with", map[string]interface{}{"Command": dimStyle.Render("core dev boot")}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.start_with", map[string]any{"Command": dimStyle.Render("core dev boot")}))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ func runVMBoot(memory, cpus int, fresh bool) error {
|
|||
}
|
||||
opts.Fresh = fresh
|
||||
|
||||
cli.Print("%s %s\n", dimStyle.Render(i18n.T("cmd.dev.vm.config_label")), i18n.T("cmd.dev.vm.config_value", map[string]interface{}{"Memory": opts.Memory, "CPUs": opts.CPUs}))
|
||||
cli.Print("%s %s\n", dimStyle.Render(i18n.T("cmd.dev.vm.config_label")), i18n.T("cmd.dev.vm.config_value", map[string]any{"Memory": opts.Memory, "CPUs": opts.CPUs}))
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.booting"))
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ func runVMBoot(memory, cpus int, fresh bool) error {
|
|||
cli.Blank()
|
||||
cli.Text(successStyle.Render(i18n.T("cmd.dev.vm.running")))
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.connect_with", map[string]interface{}{"Command": dimStyle.Render("core dev shell")}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.connect_with", map[string]any{"Command": dimStyle.Render("core dev shell")}))
|
||||
cli.Print("%s %s\n", i18n.T("cmd.dev.vm.ssh_port"), dimStyle.Render("2222"))
|
||||
|
||||
return nil
|
||||
|
|
@ -228,7 +228,7 @@ func runVMStatus() error {
|
|||
} else {
|
||||
cli.Print("%s %s\n", dimStyle.Render(i18n.T("cmd.dev.vm.installed_label")), errorStyle.Render(i18n.T("cmd.dev.vm.installed_no")))
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.install_with", map[string]interface{}{"Command": dimStyle.Render("core dev install")}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.install_with", map[string]any{"Command": dimStyle.Render("core dev install")}))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ func runVMStatus() error {
|
|||
} else {
|
||||
cli.Print("%s %s\n", dimStyle.Render(i18n.Label("status")), dimStyle.Render(i18n.T("common.status.stopped")))
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.start_with", map[string]interface{}{"Command": dimStyle.Render("core dev boot")}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.start_with", map[string]any{"Command": dimStyle.Render("core dev boot")}))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -474,7 +474,7 @@ func runVMUpdate(apply bool) error {
|
|||
cli.Blank()
|
||||
|
||||
if !apply {
|
||||
cli.Text(i18n.T("cmd.dev.vm.run_to_update", map[string]interface{}{"Command": dimStyle.Render("core dev update --apply")}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.run_to_update", map[string]any{"Command": dimStyle.Render("core dev update --apply")}))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -504,7 +504,7 @@ func runVMUpdate(apply bool) error {
|
|||
|
||||
elapsed := time.Since(start).Round(time.Second)
|
||||
cli.Blank()
|
||||
cli.Text(i18n.T("cmd.dev.vm.updated_in", map[string]interface{}{"Duration": elapsed}))
|
||||
cli.Text(i18n.T("cmd.dev.vm.updated_in", map[string]any{"Duration": elapsed}))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,9 +174,9 @@ func runWork(registryPath string, statusOnly, autoCommit bool) error {
|
|||
}
|
||||
|
||||
cli.Blank()
|
||||
cli.Print("%s\n", i18n.T("common.count.repos_unpushed", map[string]interface{}{"Count": len(aheadRepos)}))
|
||||
cli.Print("%s\n", i18n.T("common.count.repos_unpushed", map[string]any{"Count": len(aheadRepos)}))
|
||||
for _, s := range aheadRepos {
|
||||
cli.Print(" %s: %s\n", s.Name, i18n.T("common.count.commits", map[string]interface{}{"Count": s.Ahead}))
|
||||
cli.Print(" %s: %s\n", s.Name, i18n.T("common.count.commits", map[string]any{"Count": s.Ahead}))
|
||||
}
|
||||
|
||||
cli.Blank()
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ func runWorkflowSync(registryPath string, workflowFile string, dryRun bool) erro
|
|||
// Find the template workflow
|
||||
templatePath := findTemplateWorkflow(registryDir, workflowFile)
|
||||
if templatePath == "" {
|
||||
return cli.Err("%s", i18n.T("cmd.dev.workflow.template_not_found", map[string]interface{}{"File": workflowFile}))
|
||||
return cli.Err("%s", i18n.T("cmd.dev.workflow.template_not_found", map[string]any{"File": workflowFile}))
|
||||
}
|
||||
|
||||
// Read template content
|
||||
|
|
@ -240,15 +240,15 @@ func runWorkflowSync(registryPath string, workflowFile string, dryRun bool) erro
|
|||
// Summary
|
||||
if dryRun {
|
||||
cli.Print("%s %s\n",
|
||||
i18n.T("cmd.dev.workflow.would_sync_count", map[string]interface{}{"Count": synced}),
|
||||
dimStyle.Render(i18n.T("cmd.dev.workflow.skipped_count", map[string]interface{}{"Count": skipped})))
|
||||
i18n.T("cmd.dev.workflow.would_sync_count", map[string]any{"Count": synced}),
|
||||
dimStyle.Render(i18n.T("cmd.dev.workflow.skipped_count", map[string]any{"Count": skipped})))
|
||||
cli.Text(i18n.T("cmd.dev.workflow.run_without_dry_run"))
|
||||
} else {
|
||||
cli.Print("%s %s\n",
|
||||
successStyle.Render(i18n.T("cmd.dev.workflow.synced_count", map[string]interface{}{"Count": synced})),
|
||||
dimStyle.Render(i18n.T("cmd.dev.workflow.skipped_count", map[string]interface{}{"Count": skipped})))
|
||||
successStyle.Render(i18n.T("cmd.dev.workflow.synced_count", map[string]any{"Count": synced})),
|
||||
dimStyle.Render(i18n.T("cmd.dev.workflow.skipped_count", map[string]any{"Count": skipped})))
|
||||
if failed > 0 {
|
||||
cli.Print("%s\n", errorStyle.Render(i18n.T("cmd.dev.workflow.failed_count", map[string]interface{}{"Count": failed})))
|
||||
cli.Print("%s\n", errorStyle.Render(i18n.T("cmd.dev.workflow.failed_count", map[string]any{"Count": failed})))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ func runDocsList(registryPath string) error {
|
|||
|
||||
docsDir := checkMark(false)
|
||||
if len(info.DocsFiles) > 0 {
|
||||
docsDir = docsFoundStyle.Render(i18n.T("common.count.files", map[string]interface{}{"Count": len(info.DocsFiles)}))
|
||||
docsDir = docsFoundStyle.Render(i18n.T("common.count.files", map[string]any{"Count": len(info.DocsFiles)}))
|
||||
}
|
||||
|
||||
cli.Print("%-20s %-8s %-8s %-10s %s\n",
|
||||
|
|
@ -69,7 +69,7 @@ func runDocsList(registryPath string) error {
|
|||
cli.Blank()
|
||||
cli.Print("%s %s\n",
|
||||
cli.KeyStyle.Render(i18n.Label("coverage")),
|
||||
i18n.T("cmd.docs.list.coverage_summary", map[string]interface{}{"WithDocs": withDocs, "WithoutDocs": withoutDocs}),
|
||||
i18n.T("cmd.docs.list.coverage_summary", map[string]any{"WithDocs": withDocs, "WithoutDocs": withoutDocs}),
|
||||
)
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ func runPHPSync(reg *repos.Registry, basePath string, outputDir string, dryRun b
|
|||
return nil
|
||||
}
|
||||
|
||||
cli.Print("\n%s %s\n\n", dimStyle.Render(i18n.T("cmd.docs.sync.found_label")), i18n.T("cmd.docs.sync.repos_with_docs", map[string]interface{}{"Count": len(docsInfo)}))
|
||||
cli.Print("\n%s %s\n\n", dimStyle.Render(i18n.T("cmd.docs.sync.found_label")), i18n.T("cmd.docs.sync.repos_with_docs", map[string]any{"Count": len(docsInfo)}))
|
||||
|
||||
// Show what will be synced
|
||||
var totalFiles int
|
||||
|
|
@ -109,7 +109,7 @@ func runPHPSync(reg *repos.Registry, basePath string, outputDir string, dryRun b
|
|||
cli.Print(" %s → %s %s\n",
|
||||
repoNameStyle.Render(info.Name),
|
||||
docsFileStyle.Render("packages/"+outName+"/"),
|
||||
dimStyle.Render(i18n.T("cmd.docs.sync.files_count", map[string]interface{}{"Count": len(info.DocsFiles)})))
|
||||
dimStyle.Render(i18n.T("cmd.docs.sync.files_count", map[string]any{"Count": len(info.DocsFiles)})))
|
||||
|
||||
for _, f := range info.DocsFiles {
|
||||
cli.Print(" %s\n", dimStyle.Render(f))
|
||||
|
|
@ -118,7 +118,7 @@ func runPHPSync(reg *repos.Registry, basePath string, outputDir string, dryRun b
|
|||
|
||||
cli.Print("\n%s %s\n",
|
||||
dimStyle.Render(i18n.Label("total")),
|
||||
i18n.T("cmd.docs.sync.total_summary", map[string]interface{}{"Files": totalFiles, "Repos": len(docsInfo), "Output": outputDir}))
|
||||
i18n.T("cmd.docs.sync.total_summary", map[string]any{"Files": totalFiles, "Repos": len(docsInfo), "Output": outputDir}))
|
||||
|
||||
if dryRun {
|
||||
cli.Print("\n%s\n", dimStyle.Render(i18n.T("cmd.docs.sync.dry_run_notice")))
|
||||
|
|
@ -167,7 +167,7 @@ func runPHPSync(reg *repos.Registry, basePath string, outputDir string, dryRun b
|
|||
synced++
|
||||
}
|
||||
|
||||
cli.Print("\n%s %s\n", successStyle.Render(i18n.T("i18n.done.sync")), i18n.T("cmd.docs.sync.synced_packages", map[string]interface{}{"Count": synced}))
|
||||
cli.Print("\n%s %s\n", successStyle.Render(i18n.T("i18n.done.sync")), i18n.T("cmd.docs.sync.synced_packages", map[string]any{"Count": synced}))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package prod
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
|
@ -56,7 +57,7 @@ func getDNSClient() (*infra.CloudNSClient, error) {
|
|||
authID := os.Getenv("CLOUDNS_AUTH_ID")
|
||||
authPass := os.Getenv("CLOUDNS_AUTH_PASSWORD")
|
||||
if authID == "" || authPass == "" {
|
||||
return nil, fmt.Errorf("CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD required")
|
||||
return nil, errors.New("CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD required")
|
||||
}
|
||||
return infra.NewCloudNSClient(authID, authPass), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package prod
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
|
@ -39,7 +40,7 @@ func init() {
|
|||
func getHCloudClient() (*infra.HCloudClient, error) {
|
||||
token := os.Getenv("HCLOUD_TOKEN")
|
||||
if token == "" {
|
||||
return nil, fmt.Errorf("HCLOUD_TOKEN environment variable required")
|
||||
return nil, errors.New("HCLOUD_TOKEN environment variable required")
|
||||
}
|
||||
return infra.NewHCloudClient(token), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package prod
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
|
@ -141,7 +142,7 @@ func stepDiscover(ctx context.Context, cfg *infra.Config) error {
|
|||
func stepLoadBalancer(ctx context.Context, cfg *infra.Config) error {
|
||||
hcloudToken := os.Getenv("HCLOUD_TOKEN")
|
||||
if hcloudToken == "" {
|
||||
return fmt.Errorf("HCLOUD_TOKEN required for load balancer management")
|
||||
return errors.New("HCLOUD_TOKEN required for load balancer management")
|
||||
}
|
||||
|
||||
hc := infra.NewHCloudClient(hcloudToken)
|
||||
|
|
@ -237,7 +238,7 @@ func stepDNS(ctx context.Context, cfg *infra.Config) error {
|
|||
authID := os.Getenv("CLOUDNS_AUTH_ID")
|
||||
authPass := os.Getenv("CLOUDNS_AUTH_PASSWORD")
|
||||
if authID == "" || authPass == "" {
|
||||
return fmt.Errorf("CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD required")
|
||||
return errors.New("CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD required")
|
||||
}
|
||||
|
||||
dns := infra.NewCloudNSClient(authID, authPass)
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func runWatch() error {
|
|||
// Check if context deadline exceeded
|
||||
if ctx.Err() != nil {
|
||||
cli.Blank()
|
||||
return log.E("qa.watch", i18n.T("cmd.qa.watch.timeout", map[string]interface{}{"Duration": watchTimeout}), nil)
|
||||
return log.E("qa.watch", i18n.T("cmd.qa.watch.timeout", map[string]any{"Duration": watchTimeout}), nil)
|
||||
}
|
||||
|
||||
runs, err := fetchWorkflowRunsForCommit(ctx, repoFullName, commitSha)
|
||||
|
|
@ -335,7 +335,7 @@ func printResults(ctx context.Context, repoFullName string, runs []WorkflowRun)
|
|||
// Exit with error if any failures
|
||||
if len(failures) > 0 {
|
||||
cli.Blank()
|
||||
return cli.Err("%s", i18n.T("cmd.qa.watch.workflows_failed", map[string]interface{}{"Count": len(failures)}))
|
||||
return cli.Err("%s", i18n.T("cmd.qa.watch.workflows_failed", map[string]any{"Count": len(failures)}))
|
||||
}
|
||||
|
||||
cli.Blank()
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ func runGitHubSetup() error {
|
|||
// Single repo mode
|
||||
repo, ok := reg.Get(ghRepo)
|
||||
if !ok {
|
||||
return errors.New(i18n.T("error.repo_not_found", map[string]interface{}{"Name": ghRepo}))
|
||||
return errors.New(i18n.T("error.repo_not_found", map[string]any{"Name": ghRepo}))
|
||||
}
|
||||
reposToProcess = []*repos.Repo{repo}
|
||||
} else if ghAll {
|
||||
|
|
|
|||
|
|
@ -159,9 +159,9 @@ func runRegistrySetupWithReg(ctx context.Context, reg *repos.Registry, registryP
|
|||
// Summary
|
||||
fmt.Println()
|
||||
fmt.Printf("%s, %s, %s\n",
|
||||
i18n.T("cmd.setup.to_clone", map[string]interface{}{"Count": len(toClone)}),
|
||||
i18n.T("cmd.setup.exist", map[string]interface{}{"Count": exists}),
|
||||
i18n.T("common.count.skipped", map[string]interface{}{"Count": skipped}))
|
||||
i18n.T("cmd.setup.to_clone", map[string]any{"Count": len(toClone)}),
|
||||
i18n.T("cmd.setup.exist", map[string]any{"Count": exists}),
|
||||
i18n.T("common.count.skipped", map[string]any{"Count": skipped}))
|
||||
|
||||
if len(toClone) == 0 {
|
||||
fmt.Printf("\n%s\n", i18n.T("cmd.setup.nothing_to_clone"))
|
||||
|
|
@ -209,12 +209,12 @@ func runRegistrySetupWithReg(ctx context.Context, reg *repos.Registry, registryP
|
|||
|
||||
// Summary
|
||||
fmt.Println()
|
||||
fmt.Printf("%s %s", successStyle.Render(i18n.Label("done")), i18n.T("cmd.setup.cloned_count", map[string]interface{}{"Count": succeeded}))
|
||||
fmt.Printf("%s %s", successStyle.Render(i18n.Label("done")), i18n.T("cmd.setup.cloned_count", map[string]any{"Count": succeeded}))
|
||||
if failed > 0 {
|
||||
fmt.Printf(", %s", errorStyle.Render(i18n.T("i18n.count.failed", failed)))
|
||||
}
|
||||
if exists > 0 {
|
||||
fmt.Printf(", %s", i18n.T("cmd.setup.already_exist_count", map[string]interface{}{"Count": exists}))
|
||||
fmt.Printf(", %s", i18n.T("cmd.setup.already_exist_count", map[string]any{"Count": exists}))
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,6 @@ func runPackageWizard(reg *repos.Registry, preselectedTypes []string) ([]string,
|
|||
|
||||
// confirmClone asks for confirmation before cloning.
|
||||
func confirmClone(count int, target string) (bool, error) {
|
||||
confirmed := cli.Confirm(i18n.T("cmd.setup.wizard.confirm_clone", map[string]interface{}{"Count": count, "Target": target}))
|
||||
confirmed := cli.Confirm(i18n.T("cmd.setup.wizard.confirm_clone", map[string]any{"Count": count, "Target": target}))
|
||||
return confirmed, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ package setup
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
|
|
@ -184,12 +185,7 @@ func (cs *ChangeSet) printByCategory(category ChangeCategory, title string) {
|
|||
fmt.Println()
|
||||
|
||||
// Print details (sorted for deterministic output)
|
||||
keys := make([]string, 0, len(c.Details))
|
||||
for k := range c.Details {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
for _, k := range slices.Sorted(maps.Keys(c.Details)) {
|
||||
fmt.Printf(" %s: %s\n", dimStyle.Render(k), c.Details[k])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func SetBranchProtection(repoFullName, branch string, config BranchProtectionCon
|
|||
}
|
||||
|
||||
// Build the protection payload
|
||||
payload := map[string]interface{}{
|
||||
payload := map[string]any{
|
||||
"enforce_admins": config.EnforceAdmins,
|
||||
"required_linear_history": config.RequireLinearHistory,
|
||||
"allow_force_pushes": config.AllowForcePushes,
|
||||
|
|
@ -115,7 +115,7 @@ func SetBranchProtection(repoFullName, branch string, config BranchProtectionCon
|
|||
|
||||
// Required pull request reviews
|
||||
if config.RequiredReviews > 0 {
|
||||
payload["required_pull_request_reviews"] = map[string]interface{}{
|
||||
payload["required_pull_request_reviews"] = map[string]any{
|
||||
"dismiss_stale_reviews": config.DismissStale,
|
||||
"require_code_owner_reviews": config.RequireCodeOwnerReviews,
|
||||
"required_approving_review_count": config.RequiredReviews,
|
||||
|
|
@ -126,7 +126,7 @@ func SetBranchProtection(repoFullName, branch string, config BranchProtectionCon
|
|||
|
||||
// Required status checks
|
||||
if len(config.RequiredStatusChecks) > 0 {
|
||||
payload["required_status_checks"] = map[string]interface{}{
|
||||
payload["required_status_checks"] = map[string]any{
|
||||
"strict": true,
|
||||
"contexts": config.RequiredStatusChecks,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ func UpdateSecurityAndAnalysis(repoFullName string, secretScanning, pushProtecti
|
|||
}
|
||||
|
||||
// Build the payload
|
||||
payload := map[string]interface{}{
|
||||
"security_and_analysis": map[string]interface{}{
|
||||
payload := map[string]any{
|
||||
"security_and_analysis": map[string]any{
|
||||
"secret_scanning": map[string]string{
|
||||
"status": boolToStatus(secretScanning),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -69,11 +69,11 @@ func CreateWebhook(repoFullName string, name string, config WebhookConfig) error
|
|||
}
|
||||
|
||||
// Build the webhook payload
|
||||
payload := map[string]interface{}{
|
||||
payload := map[string]any{
|
||||
"name": "web",
|
||||
"active": true,
|
||||
"events": config.Events,
|
||||
"config": map[string]interface{}{
|
||||
"config": map[string]any{
|
||||
"url": config.URL,
|
||||
"content_type": config.ContentType,
|
||||
"insecure_ssl": "0",
|
||||
|
|
@ -85,7 +85,7 @@ func CreateWebhook(repoFullName string, name string, config WebhookConfig) error
|
|||
}
|
||||
|
||||
if config.Secret != "" {
|
||||
configMap := payload["config"].(map[string]interface{})
|
||||
configMap := payload["config"].(map[string]any)
|
||||
configMap["secret"] = config.Secret
|
||||
}
|
||||
|
||||
|
|
@ -111,10 +111,10 @@ func UpdateWebhook(repoFullName string, hookID int, config WebhookConfig) error
|
|||
return fmt.Errorf("invalid repo format: %s", repoFullName)
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
payload := map[string]any{
|
||||
"active": true,
|
||||
"events": config.Events,
|
||||
"config": map[string]interface{}{
|
||||
"config": map[string]any{
|
||||
"url": config.URL,
|
||||
"content_type": config.ContentType,
|
||||
"insecure_ssl": "0",
|
||||
|
|
@ -126,7 +126,7 @@ func UpdateWebhook(repoFullName string, hookID int, config WebhookConfig) error
|
|||
}
|
||||
|
||||
if config.Secret != "" {
|
||||
configMap := payload["config"].(map[string]interface{})
|
||||
configMap := payload["config"].(map[string]any)
|
||||
configMap["secret"] = config.Secret
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ func runContainer(image, name string, detach bool, memory, cpus, sshPort int) er
|
|||
fmt.Printf("%s %s\n", successStyle.Render(i18n.Label("started")), c.ID)
|
||||
fmt.Printf("%s %d\n", dimStyle.Render(i18n.T("cmd.vm.label.pid")), c.PID)
|
||||
fmt.Println()
|
||||
fmt.Println(i18n.T("cmd.vm.hint.view_logs", map[string]interface{}{"ID": c.ID[:8]}))
|
||||
fmt.Println(i18n.T("cmd.vm.hint.stop", map[string]interface{}{"ID": c.ID[:8]}))
|
||||
fmt.Println(i18n.T("cmd.vm.hint.view_logs", map[string]any{"ID": c.ID[:8]}))
|
||||
fmt.Println(i18n.T("cmd.vm.hint.stop", map[string]any{"ID": c.ID[:8]}))
|
||||
} else {
|
||||
fmt.Printf("\n%s %s\n", dimStyle.Render(i18n.T("cmd.vm.label.container_stopped")), c.ID)
|
||||
}
|
||||
|
|
@ -261,11 +261,11 @@ func resolveContainerID(manager *container.LinuxKitManager, partialID string) (s
|
|||
|
||||
switch len(matches) {
|
||||
case 0:
|
||||
return "", errors.New(i18n.T("cmd.vm.error.no_match", map[string]interface{}{"ID": partialID}))
|
||||
return "", errors.New(i18n.T("cmd.vm.error.no_match", map[string]any{"ID": partialID}))
|
||||
case 1:
|
||||
return matches[0].ID, nil
|
||||
default:
|
||||
return "", errors.New(i18n.T("cmd.vm.error.multiple_match", map[string]interface{}{"ID": partialID}))
|
||||
return "", errors.New(i18n.T("cmd.vm.error.multiple_match", map[string]any{"ID": partialID}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,8 +204,8 @@ func RunFromTemplate(templateName string, vars map[string]string, runOpts contai
|
|||
fmt.Printf("%s %s\n", successStyle.Render(i18n.T("common.label.started")), c.ID)
|
||||
fmt.Printf("%s %d\n", dimStyle.Render(i18n.T("cmd.vm.label.pid")), c.PID)
|
||||
fmt.Println()
|
||||
fmt.Println(i18n.T("cmd.vm.hint.view_logs", map[string]interface{}{"ID": c.ID[:8]}))
|
||||
fmt.Println(i18n.T("cmd.vm.hint.stop", map[string]interface{}{"ID": c.ID[:8]}))
|
||||
fmt.Println(i18n.T("cmd.vm.hint.view_logs", map[string]any{"ID": c.ID[:8]}))
|
||||
fmt.Println(i18n.T("cmd.vm.hint.stop", map[string]any{"ID": c.ID[:8]}))
|
||||
} else {
|
||||
fmt.Printf("\n%s %s\n", dimStyle.Render(i18n.T("cmd.vm.label.container_stopped")), c.ID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package container
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -249,7 +250,7 @@ func DetectHypervisor() (Hypervisor, error) {
|
|||
return qemu, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no hypervisor available: install qemu or hyperkit (macOS)")
|
||||
return nil, errors.New("no hypervisor available: install qemu or hyperkit (macOS)")
|
||||
}
|
||||
|
||||
// GetHypervisor returns a specific hypervisor by name.
|
||||
|
|
@ -258,13 +259,13 @@ func GetHypervisor(name string) (Hypervisor, error) {
|
|||
case "qemu":
|
||||
h := NewQemuHypervisor()
|
||||
if !h.Available() {
|
||||
return nil, fmt.Errorf("qemu is not available")
|
||||
return nil, errors.New("qemu is not available")
|
||||
}
|
||||
return h, nil
|
||||
case "hyperkit":
|
||||
h := NewHyperkitHypervisor()
|
||||
if !h.Available() {
|
||||
return nil, fmt.Errorf("hyperkit is not available (requires macOS)")
|
||||
return nil, errors.New("hyperkit is not available (requires macOS)")
|
||||
}
|
||||
return h, nil
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package coolify
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
|
@ -41,10 +42,10 @@ func DefaultConfig() Config {
|
|||
// NewClient creates a new Coolify client.
|
||||
func NewClient(cfg Config) (*Client, error) {
|
||||
if cfg.BaseURL == "" {
|
||||
return nil, fmt.Errorf("COOLIFY_URL not set")
|
||||
return nil, errors.New("COOLIFY_URL not set")
|
||||
}
|
||||
if cfg.APIToken == "" {
|
||||
return nil, fmt.Errorf("COOLIFY_TOKEN not set")
|
||||
return nil, errors.New("COOLIFY_TOKEN not set")
|
||||
}
|
||||
|
||||
// Initialize Python runtime
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ func (t *Toolkit) FindTODOs(dir string) ([]TODO, error) {
|
|||
return nil, nil
|
||||
}
|
||||
if err != nil && exitCode != 1 {
|
||||
return nil, fmt.Errorf("git grep failed (exit %d): %s\n%s", exitCode, err, stderr)
|
||||
return nil, fmt.Errorf("git grep failed (exit %d): %w\n%s", exitCode, err, stderr)
|
||||
}
|
||||
|
||||
var todos []TODO
|
||||
|
|
@ -191,7 +191,7 @@ func (t *Toolkit) FindTODOs(dir string) ([]TODO, error) {
|
|||
func (t *Toolkit) AuditDeps() ([]Vulnerability, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("govulncheck", "./...")
|
||||
if err != nil && exitCode != 0 && !strings.Contains(stdout, "Vulnerability") {
|
||||
return nil, fmt.Errorf("govulncheck failed (exit %d): %s\n%s", exitCode, err, stderr)
|
||||
return nil, fmt.Errorf("govulncheck failed (exit %d): %w\n%s", exitCode, err, stderr)
|
||||
}
|
||||
|
||||
var vulns []Vulnerability
|
||||
|
|
@ -240,7 +240,7 @@ func (t *Toolkit) AuditDeps() ([]Vulnerability, error) {
|
|||
func (t *Toolkit) DiffStat() (DiffSummary, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("git", "diff", "--stat")
|
||||
if err != nil && exitCode != 0 {
|
||||
return DiffSummary{}, fmt.Errorf("git diff failed (exit %d): %s\n%s", exitCode, err, stderr)
|
||||
return DiffSummary{}, fmt.Errorf("git diff failed (exit %d): %w\n%s", exitCode, err, stderr)
|
||||
}
|
||||
|
||||
var s DiffSummary
|
||||
|
|
@ -273,7 +273,7 @@ func (t *Toolkit) DiffStat() (DiffSummary, error) {
|
|||
func (t *Toolkit) UncommittedFiles() ([]string, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("git", "status", "--porcelain")
|
||||
if err != nil && exitCode != 0 {
|
||||
return nil, fmt.Errorf("git status failed: %s\n%s", err, stderr)
|
||||
return nil, fmt.Errorf("git status failed: %w\n%s", err, stderr)
|
||||
}
|
||||
var files []string
|
||||
for line := range strings.SplitSeq(strings.TrimSpace(stdout), "\n") {
|
||||
|
|
@ -371,7 +371,7 @@ func (t *Toolkit) Build(targets ...string) ([]BuildResult, error) {
|
|||
func (t *Toolkit) TestCount(pkg string) (int, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("go", "test", "-list", ".*", pkg)
|
||||
if err != nil && exitCode != 0 {
|
||||
return 0, fmt.Errorf("go test -list failed: %s\n%s", err, stderr)
|
||||
return 0, fmt.Errorf("go test -list failed: %w\n%s", err, stderr)
|
||||
}
|
||||
count := 0
|
||||
for line := range strings.SplitSeq(strings.TrimSpace(stdout), "\n") {
|
||||
|
|
@ -389,7 +389,7 @@ func (t *Toolkit) Coverage(pkg string) ([]CoverageReport, error) {
|
|||
}
|
||||
stdout, stderr, exitCode, err := t.Run("go", "test", "-cover", pkg)
|
||||
if err != nil && exitCode != 0 && !strings.Contains(stdout, "coverage:") {
|
||||
return nil, fmt.Errorf("go test -cover failed (exit %d): %s\n%s", exitCode, err, stderr)
|
||||
return nil, fmt.Errorf("go test -cover failed (exit %d): %w\n%s", exitCode, err, stderr)
|
||||
}
|
||||
|
||||
var reports []CoverageReport
|
||||
|
|
@ -443,7 +443,7 @@ func (t *Toolkit) RaceDetect(pkg string) ([]RaceCondition, error) {
|
|||
func (t *Toolkit) Complexity(threshold int) ([]ComplexFunc, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("gocyclo", "-over", strconv.Itoa(threshold), ".")
|
||||
if err != nil && exitCode == -1 {
|
||||
return nil, fmt.Errorf("gocyclo not available: %s\n%s", err, stderr)
|
||||
return nil, fmt.Errorf("gocyclo not available: %w\n%s", err, stderr)
|
||||
}
|
||||
|
||||
var funcs []ComplexFunc
|
||||
|
|
@ -476,7 +476,7 @@ func (t *Toolkit) Complexity(threshold int) ([]ComplexFunc, error) {
|
|||
func (t *Toolkit) DepGraph(pkg string) (*Graph, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("go", "mod", "graph")
|
||||
if err != nil && exitCode != 0 {
|
||||
return nil, fmt.Errorf("go mod graph failed (exit %d): %s\n%s", exitCode, err, stderr)
|
||||
return nil, fmt.Errorf("go mod graph failed (exit %d): %w\n%s", exitCode, err, stderr)
|
||||
}
|
||||
|
||||
graph := &Graph{Edges: make(map[string][]string)}
|
||||
|
|
@ -503,7 +503,7 @@ func (t *Toolkit) DepGraph(pkg string) (*Graph, error) {
|
|||
func (t *Toolkit) GitLog(n int) ([]Commit, error) {
|
||||
stdout, stderr, exitCode, err := t.Run("git", "log", fmt.Sprintf("-n%d", n), "--format=%H|%an|%aI|%s")
|
||||
if err != nil && exitCode != 0 {
|
||||
return nil, fmt.Errorf("git log failed (exit %d): %s\n%s", exitCode, err, stderr)
|
||||
return nil, fmt.Errorf("git log failed (exit %d): %w\n%s", exitCode, err, stderr)
|
||||
}
|
||||
|
||||
var commits []Commit
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package devops
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -116,14 +117,14 @@ func DefaultBootOptions() BootOptions {
|
|||
// Boot starts the dev environment.
|
||||
func (d *DevOps) Boot(ctx context.Context, opts BootOptions) error {
|
||||
if !d.images.IsInstalled() {
|
||||
return fmt.Errorf("dev image not installed (run 'core dev install' first)")
|
||||
return errors.New("dev image not installed (run 'core dev install' first)")
|
||||
}
|
||||
|
||||
// Check if already running
|
||||
if !opts.Fresh {
|
||||
running, err := d.IsRunning(ctx)
|
||||
if err == nil && running {
|
||||
return fmt.Errorf("dev environment already running (use 'core dev stop' first or --fresh)")
|
||||
return errors.New("dev environment already running (use 'core dev stop' first or --fresh)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +178,7 @@ func (d *DevOps) Stop(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
if c == nil {
|
||||
return fmt.Errorf("dev environment not found")
|
||||
return errors.New("dev environment not found")
|
||||
}
|
||||
return d.container.Stop(ctx, c.ID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package devops
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -109,7 +110,7 @@ func (m *ImageManager) Install(ctx context.Context, progress func(downloaded, to
|
|||
}
|
||||
}
|
||||
if src == nil {
|
||||
return fmt.Errorf("no image source available")
|
||||
return errors.New("no image source available")
|
||||
}
|
||||
|
||||
// Get version
|
||||
|
|
@ -139,7 +140,7 @@ func (m *ImageManager) Install(ctx context.Context, progress func(downloaded, to
|
|||
func (m *ImageManager) CheckUpdate(ctx context.Context) (current, latest string, hasUpdate bool, err error) {
|
||||
info, ok := m.manifest.Images[ImageName()]
|
||||
if !ok {
|
||||
return "", "", false, fmt.Errorf("image not installed")
|
||||
return "", "", false, errors.New("image not installed")
|
||||
}
|
||||
current = info.Version
|
||||
|
||||
|
|
@ -152,7 +153,7 @@ func (m *ImageManager) CheckUpdate(ctx context.Context) (current, latest string,
|
|||
}
|
||||
}
|
||||
if src == nil {
|
||||
return current, "", false, fmt.Errorf("no image source available")
|
||||
return current, "", false, errors.New("no image source available")
|
||||
}
|
||||
|
||||
latest, err = src.LatestVersion(ctx)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package devops
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -23,7 +24,7 @@ func (d *DevOps) Serve(ctx context.Context, projectDir string, opts ServeOptions
|
|||
return err
|
||||
}
|
||||
if !running {
|
||||
return fmt.Errorf("dev environment not running (run 'core dev boot' first)")
|
||||
return errors.New("dev environment not running (run 'core dev boot' first)")
|
||||
}
|
||||
|
||||
if opts.Port == 0 {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package devops
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -20,7 +21,7 @@ func (d *DevOps) Shell(ctx context.Context, opts ShellOptions) error {
|
|||
return err
|
||||
}
|
||||
if !running {
|
||||
return fmt.Errorf("dev environment not running (run 'core dev boot' first)")
|
||||
return errors.New("dev environment not running (run 'core dev boot' first)")
|
||||
}
|
||||
|
||||
if opts.Console {
|
||||
|
|
@ -61,7 +62,7 @@ func (d *DevOps) serialConsole(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
if c == nil {
|
||||
return fmt.Errorf("console not available: container not found")
|
||||
return errors.New("console not available: container not found")
|
||||
}
|
||||
|
||||
// Use socat to connect to the console socket
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package devops
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -37,7 +38,7 @@ func ensureHostKey(ctx context.Context, port int) error {
|
|||
}
|
||||
|
||||
if len(out) == 0 {
|
||||
return fmt.Errorf("ssh-keyscan returned no keys")
|
||||
return errors.New("ssh-keyscan returned no keys")
|
||||
}
|
||||
|
||||
// Read existing known_hosts to avoid duplicates
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package devops
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -38,7 +39,7 @@ func (d *DevOps) Test(ctx context.Context, projectDir string, opts TestOptions)
|
|||
return err
|
||||
}
|
||||
if !running {
|
||||
return fmt.Errorf("dev environment not running (run 'core dev boot' first)")
|
||||
return errors.New("dev environment not running (run 'core dev boot' first)")
|
||||
}
|
||||
|
||||
var cmd string
|
||||
|
|
@ -63,7 +64,7 @@ func (d *DevOps) Test(ctx context.Context, projectDir string, opts TestOptions)
|
|||
} else {
|
||||
cmd = DetectTestCommand(d.medium, projectDir)
|
||||
if cmd == "" {
|
||||
return fmt.Errorf("could not detect test command (create .core/test.yaml)")
|
||||
return errors.New("could not detect test command (create .core/test.yaml)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +178,7 @@ func hasComposerScript(m io.Medium, projectDir, script string) bool {
|
|||
}
|
||||
|
||||
var pkg struct {
|
||||
Scripts map[string]interface{} `json:"scripts"`
|
||||
Scripts map[string]any `json:"scripts"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(content), &pkg); err != nil {
|
||||
return false
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -4,8 +4,8 @@ forge.lthn.ai/core/cli v0.0.3 h1:Qd/ACf8as4cwWoqAzkLIPF86NhXzfkkt1t/6xmgznVw=
|
|||
forge.lthn.ai/core/cli v0.0.3/go.mod h1:xa3Nqw3sUtYYJ1k+1jYul18tgs6sBevCUsGsHJI1hHA=
|
||||
forge.lthn.ai/core/go v0.0.1 h1:ubk4nmkA3treOUNgPS28wKd1jB6cUlEQUV7jDdGa3zM=
|
||||
forge.lthn.ai/core/go v0.0.1/go.mod h1:59YsnuMaAGQUxIhX68oK2/HnhQJEPWL1iEZhDTrNCbY=
|
||||
forge.lthn.ai/core/go-agentic v0.0.2 h1:dsngOpUp8ATUWlM1O8gqFgS4FLJG0ngDvsXNQJigBDA=
|
||||
forge.lthn.ai/core/go-agentic v0.0.2/go.mod h1:KwalcfzQACtedb7wNe/7U/59PtdpvezqMJmmvhTptOY=
|
||||
forge.lthn.ai/core/go-agentic v0.0.2 h1:G2nhiFY0j66A8/dyPXrS3CDYT1VLIin//GDszz4zEEo=
|
||||
forge.lthn.ai/core/go-agentic v0.0.2/go.mod h1:wTZRajs+rt0YJbRk26ijC1sfICbg8O2782ZhCz2tv/k=
|
||||
forge.lthn.ai/core/go-crypt v0.0.2 h1:m8mCIrmC0tserVx9bfmrB8h4GtgAgQeedBPeNBvCxx0=
|
||||
forge.lthn.ai/core/go-crypt v0.0.2/go.mod h1:+JoZ4mwjzTklysI/DI7f6/0iocdJoJG2ZF/nQy6HTuI=
|
||||
forge.lthn.ai/core/go-scm v0.0.2 h1:Ue+gS5vxZkDgTvQrqYu9QdaqEezuTV1kZY3TMqM2uho=
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
|
|
@ -269,18 +269,11 @@ func formatChangelog(commits []ConventionalCommit, version string) string {
|
|||
// Any remaining types not in the order list
|
||||
var remainingTypes []string
|
||||
for commitType := range grouped {
|
||||
found := false
|
||||
for _, t := range commitTypeOrder {
|
||||
if t == commitType {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
if !slices.Contains(commitTypeOrder, commitType) {
|
||||
remainingTypes = append(remainingTypes, commitType)
|
||||
}
|
||||
}
|
||||
sort.Strings(remainingTypes)
|
||||
slices.Sort(remainingTypes)
|
||||
|
||||
for _, commitType := range remainingTypes {
|
||||
commits := grouped[commitType]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -47,7 +48,7 @@ func (p *AURPublisher) Publish(ctx context.Context, release *Release, pubCfg Pub
|
|||
cfg := p.parseConfig(pubCfg, relCfg)
|
||||
|
||||
if cfg.Maintainer == "" {
|
||||
return fmt.Errorf("aur.Publish: maintainer is required (set publish.aur.maintainer in config)")
|
||||
return errors.New("aur.Publish: maintainer is required (set publish.aur.maintainer in config)")
|
||||
}
|
||||
|
||||
repo := ""
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -231,7 +232,7 @@ func (p *ChocolateyPublisher) pushToChocolatey(ctx context.Context, packageDir s
|
|||
// Check for CHOCOLATEY_API_KEY
|
||||
apiKey := os.Getenv("CHOCOLATEY_API_KEY")
|
||||
if apiKey == "" {
|
||||
return fmt.Errorf("chocolatey.Publish: CHOCOLATEY_API_KEY environment variable is required for push")
|
||||
return errors.New("chocolatey.Publish: CHOCOLATEY_API_KEY environment variable is required for push")
|
||||
}
|
||||
|
||||
// Pack the package
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package publishers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -250,7 +251,7 @@ func (p *DockerPublisher) ensureBuildx(ctx context.Context) error {
|
|||
// Check if buildx is available
|
||||
cmd := exec.CommandContext(ctx, "docker", "buildx", "version")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("docker: buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/")
|
||||
return errors.New("docker: buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/")
|
||||
}
|
||||
|
||||
// Check if we have a builder, create one if not
|
||||
|
|
@ -272,7 +273,7 @@ func (p *DockerPublisher) ensureBuildx(ctx context.Context) error {
|
|||
func validateDockerCli() error {
|
||||
cmd := exec.Command("docker", "--version")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("docker: docker CLI not found. Install it from https://docs.docker.com/get-docker/")
|
||||
return errors.New("docker: docker CLI not found. Install it from https://docs.docker.com/get-docker/")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package publishers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -146,18 +147,18 @@ func validateGhCli() error {
|
|||
// Check if gh is installed
|
||||
cmd := exec.Command("gh", "--version")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("github: gh CLI not found. Install it from https://cli.github.com")
|
||||
return errors.New("github: gh CLI not found. Install it from https://cli.github.com")
|
||||
}
|
||||
|
||||
// Check if authenticated
|
||||
cmd = exec.Command("gh", "auth", "status")
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("github: not authenticated with gh CLI. Run 'gh auth login' first")
|
||||
return errors.New("github: not authenticated with gh CLI. Run 'gh auth login' first")
|
||||
}
|
||||
|
||||
if !strings.Contains(string(output), "Logged in") {
|
||||
return fmt.Errorf("github: not authenticated with gh CLI. Run 'gh auth login' first")
|
||||
return errors.New("github: not authenticated with gh CLI. Run 'gh auth login' first")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -57,7 +58,7 @@ func (p *HomebrewPublisher) Publish(ctx context.Context, release *Release, pubCf
|
|||
|
||||
// Validate configuration
|
||||
if cfg.Tap == "" && (cfg.Official == nil || !cfg.Official.Enabled) {
|
||||
return fmt.Errorf("homebrew.Publish: tap is required (set publish.homebrew.tap in config)")
|
||||
return errors.New("homebrew.Publish: tap is required (set publish.homebrew.tap in config)")
|
||||
}
|
||||
|
||||
// Get repository and project info
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package publishers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -48,7 +49,7 @@ func (p *LinuxKitPublisher) Publish(ctx context.Context, release *Release, pubCf
|
|||
|
||||
// Validate config file exists
|
||||
if release.FS == nil {
|
||||
return fmt.Errorf("linuxkit.Publish: release filesystem (FS) is nil")
|
||||
return errors.New("linuxkit.Publish: release filesystem (FS) is nil")
|
||||
}
|
||||
if !release.FS.Exists(lkCfg.Config) {
|
||||
return fmt.Errorf("linuxkit.Publish: config file not found: %s", lkCfg.Config)
|
||||
|
|
@ -297,7 +298,7 @@ func (p *LinuxKitPublisher) getFormatExtension(format string) string {
|
|||
func validateLinuxKitCli() error {
|
||||
cmd := exec.Command("linuxkit", "version")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("linuxkit: linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit")
|
||||
return errors.New("linuxkit: linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -47,7 +48,7 @@ func (p *NpmPublisher) Publish(ctx context.Context, release *Release, pubCfg Pub
|
|||
|
||||
// Validate configuration
|
||||
if npmCfg.Package == "" {
|
||||
return fmt.Errorf("npm.Publish: package name is required (set publish.npm.package in config)")
|
||||
return errors.New("npm.Publish: package name is required (set publish.npm.package in config)")
|
||||
}
|
||||
|
||||
// Get repository
|
||||
|
|
@ -162,7 +163,7 @@ func (p *NpmPublisher) dryRunPublish(m io.Medium, data npmTemplateData, cfg *Npm
|
|||
func (p *NpmPublisher) executePublish(ctx context.Context, m io.Medium, data npmTemplateData, cfg *NpmConfig) error {
|
||||
// Check for NPM_TOKEN
|
||||
if os.Getenv("NPM_TOKEN") == "" {
|
||||
return fmt.Errorf("npm.Publish: NPM_TOKEN environment variable is required")
|
||||
return errors.New("npm.Publish: NPM_TOKEN environment variable is required")
|
||||
}
|
||||
|
||||
// Create temp directory for package
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -45,7 +46,7 @@ func (p *ScoopPublisher) Publish(ctx context.Context, release *Release, pubCfg P
|
|||
cfg := p.parseConfig(pubCfg, relCfg)
|
||||
|
||||
if cfg.Bucket == "" && (cfg.Official == nil || !cfg.Official.Enabled) {
|
||||
return fmt.Errorf("scoop.Publish: bucket is required (set publish.scoop.bucket in config)")
|
||||
return errors.New("scoop.Publish: bucket is required (set publish.scoop.bucket in config)")
|
||||
}
|
||||
|
||||
repo := ""
|
||||
|
|
|
|||
|
|
@ -5,14 +5,15 @@ package release
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go-devops/build"
|
||||
"forge.lthn.ai/core/go-devops/build/builders"
|
||||
"forge.lthn.ai/core/go/pkg/io"
|
||||
"forge.lthn.ai/core/go-devops/release/publishers"
|
||||
"forge.lthn.ai/core/go/pkg/io"
|
||||
)
|
||||
|
||||
// Release represents a release with its version, artifacts, and changelog.
|
||||
|
|
@ -34,7 +35,7 @@ type Release struct {
|
|||
// If dryRun is true, it will show what would be done without actually publishing.
|
||||
func Publish(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("release.Publish: config is nil")
|
||||
return nil, errors.New("release.Publish: config is nil")
|
||||
}
|
||||
|
||||
m := io.Local
|
||||
|
|
@ -67,7 +68,7 @@ func Publish(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) {
|
|||
}
|
||||
|
||||
if len(artifacts) == 0 {
|
||||
return nil, fmt.Errorf("release.Publish: no artifacts found in dist/\nRun 'core build' first to create artifacts")
|
||||
return nil, errors.New("release.Publish: no artifacts found in dist/\nRun 'core build' first to create artifacts")
|
||||
}
|
||||
|
||||
// Step 3: Generate changelog
|
||||
|
|
@ -109,7 +110,7 @@ func Publish(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) {
|
|||
// findArtifacts discovers pre-built artifacts in the dist directory.
|
||||
func findArtifacts(m io.Medium, distDir string) ([]build.Artifact, error) {
|
||||
if !m.IsDir(distDir) {
|
||||
return nil, fmt.Errorf("dist/ directory not found")
|
||||
return nil, errors.New("dist/ directory not found")
|
||||
}
|
||||
|
||||
var artifacts []build.Artifact
|
||||
|
|
@ -145,7 +146,7 @@ func findArtifacts(m io.Medium, distDir string) ([]build.Artifact, error) {
|
|||
// If dryRun is true, it will show what would be done without actually publishing.
|
||||
func Run(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("release.Run: config is nil")
|
||||
return nil, errors.New("release.Run: config is nil")
|
||||
}
|
||||
|
||||
m := io.Local
|
||||
|
|
@ -317,9 +318,9 @@ func getBuilder(projectType build.ProjectType) (build.Builder, error) {
|
|||
case build.ProjectTypeGo:
|
||||
return builders.NewGoBuilder(), nil
|
||||
case build.ProjectTypeNode:
|
||||
return nil, fmt.Errorf("node.js builder not yet implemented")
|
||||
return nil, errors.New("node.js builder not yet implemented")
|
||||
case build.ProjectTypePHP:
|
||||
return nil, fmt.Errorf("PHP builder not yet implemented")
|
||||
return nil, errors.New("PHP builder not yet implemented")
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported project type: %s", projectType)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package release
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"forge.lthn.ai/core/go-devops/sdk"
|
||||
|
|
@ -22,10 +23,10 @@ type SDKRelease struct {
|
|||
// If dryRun is true, it shows what would be done without generating.
|
||||
func RunSDK(ctx context.Context, cfg *Config, dryRun bool) (*SDKRelease, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("release.RunSDK: config is nil")
|
||||
return nil, errors.New("release.RunSDK: config is nil")
|
||||
}
|
||||
if cfg.SDK == nil {
|
||||
return nil, fmt.Errorf("release.RunSDK: sdk not configured in .core/release.yaml")
|
||||
return nil, errors.New("release.RunSDK: sdk not configured in .core/release.yaml")
|
||||
}
|
||||
|
||||
projectDir := cfg.projectDir
|
||||
|
|
@ -51,7 +52,7 @@ func RunSDK(ctx context.Context, cfg *Config, dryRun bool) (*SDKRelease, error)
|
|||
fmt.Printf("Warning: diff check failed: %v\n", err)
|
||||
} else if breaking {
|
||||
if cfg.SDK.Diff.FailOnBreaking {
|
||||
return nil, fmt.Errorf("release.RunSDK: breaking API changes detected")
|
||||
return nil, errors.New("release.RunSDK: breaking API changes detected")
|
||||
}
|
||||
fmt.Printf("Warning: breaking API changes detected\n")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package sdk
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -46,14 +47,14 @@ func (s *SDK) DetectSpec() (string, error) {
|
|||
return specPath, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("sdk.DetectSpec: no OpenAPI spec found (checked config, common paths, Scramble)")
|
||||
return "", errors.New("sdk.DetectSpec: no OpenAPI spec found (checked config, common paths, Scramble)")
|
||||
}
|
||||
|
||||
// detectScramble checks for Laravel Scramble and exports the spec.
|
||||
func (s *SDK) detectScramble() (string, error) {
|
||||
composerPath := filepath.Join(s.projectDir, "composer.json")
|
||||
if !coreio.Local.IsFile(composerPath) {
|
||||
return "", fmt.Errorf("no composer.json")
|
||||
return "", errors.New("no composer.json")
|
||||
}
|
||||
|
||||
// Check for scramble in composer.json
|
||||
|
|
@ -64,11 +65,11 @@ func (s *SDK) detectScramble() (string, error) {
|
|||
|
||||
// Simple check for scramble package
|
||||
if !containsScramble(data) {
|
||||
return "", fmt.Errorf("scramble not found in composer.json")
|
||||
return "", errors.New("scramble not found in composer.json")
|
||||
}
|
||||
|
||||
// TODO: Run php artisan scramble:export
|
||||
return "", fmt.Errorf("scramble export not implemented")
|
||||
return "", errors.New("scramble export not implemented")
|
||||
}
|
||||
|
||||
// containsScramble checks if composer.json includes scramble.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package generators
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -37,7 +38,7 @@ func (g *PHPGenerator) Install() string {
|
|||
// Generate creates SDK from OpenAPI spec.
|
||||
func (g *PHPGenerator) Generate(ctx context.Context, opts Options) error {
|
||||
if !g.Available() {
|
||||
return fmt.Errorf("php.Generate: Docker is required but not available")
|
||||
return errors.New("php.Generate: Docker is required but not available")
|
||||
}
|
||||
|
||||
if err := coreio.Local.EnsureDir(opts.OutputDir); err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue