2026-01-28 18:33:11 +00:00
|
|
|
// Package release provides release automation with changelog generation and publishing.
|
|
|
|
|
// It orchestrates the build system, changelog generation, and publishing to targets
|
|
|
|
|
// like GitHub Releases.
|
|
|
|
|
package release
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
"path/filepath"
|
2026-01-29 12:48:28 +00:00
|
|
|
"strings"
|
2026-01-28 18:33:11 +00:00
|
|
|
|
|
|
|
|
"github.com/host-uk/core/pkg/build"
|
|
|
|
|
"github.com/host-uk/core/pkg/build/builders"
|
docs(audit): add dependency security audit report (#248)
* feat(devops): migrate filesystem operations to io.Local abstraction
Migrate config.go:
- os.ReadFile → io.Local.Read
Migrate devops.go:
- os.Stat → io.Local.IsFile
Migrate images.go:
- os.MkdirAll → io.Local.EnsureDir
- os.Stat → io.Local.IsFile
- os.ReadFile → io.Local.Read
- os.WriteFile → io.Local.Write
Migrate test.go:
- os.ReadFile → io.Local.Read
- os.Stat → io.Local.IsFile
Migrate claude.go:
- os.Stat → io.Local.IsDir
Updated tests to reflect improved behavior:
- Manifest.Save() now creates parent directories
- hasFile() correctly returns false for directories
Part of #101 (io.Medium migration tracking issue).
Closes #107
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore(io): migrate remaining packages to io.Local abstraction
Migrate filesystem operations to use the io.Local abstraction for
improved security, testability, and consistency:
- pkg/cache: Replace os.ReadFile, WriteFile, Remove, RemoveAll with
io.Local equivalents. io.Local.Write creates parent dirs automatically.
- pkg/agentic: Migrate config.go and context.go to use io.Local for
reading config files and gathering file context.
- pkg/repos: Use io.Local.Read, Exists, IsDir, List for registry
operations and git repo detection.
- pkg/release: Use io.Local for config loading, existence checks,
and artifact discovery.
- pkg/devops/sources: Use io.Local.EnsureDir for CDN download.
All paths are converted to absolute using filepath.Abs() before
calling io.Local methods to handle relative paths correctly.
Closes #104, closes #106, closes #108, closes #111
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore(io): migrate pkg/cli and pkg/container to io.Local abstraction
Continue io.Medium migration for the remaining packages:
- pkg/cli/daemon.go: PIDFile Acquire/Release now use io.Local.Read,
Delete, and Write for managing daemon PID files.
- pkg/container/state.go: LoadState and SaveState use io.Local for
JSON state persistence. EnsureLogsDir uses io.Local.EnsureDir.
- pkg/container/templates.go: Template loading and directory scanning
now use io.Local.IsFile, IsDir, Read, and List.
- pkg/container/linuxkit.go: Image validation uses io.Local.IsFile,
log file check uses io.Local.IsFile. Streaming log file creation
(os.Create) remains unchanged as io.Local doesn't support streaming.
Closes #105, closes #107
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs(audit): add dependency security audit report
Complete security audit of all project dependencies:
- Run govulncheck: No vulnerabilities found
- Run go mod verify: All modules verified
- Document 15 direct dependencies and 161 indirect
- Assess supply chain risks: Low risk overall
- Verify lock files are committed with integrity hashes
- Provide CI integration recommendations
Closes #185
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(ci): build core CLI from source instead of downloading release
The workflows were trying to download from a non-existent release URL.
Now builds the CLI directly using `go build` with version injection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: trigger CI with updated workflow
* chore(ci): add workflow_dispatch trigger for manual runs
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 08:04:26 +00:00
|
|
|
"github.com/host-uk/core/pkg/io"
|
2026-01-28 18:33:11 +00:00
|
|
|
"github.com/host-uk/core/pkg/release/publishers"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Release represents a release with its version, artifacts, and changelog.
|
|
|
|
|
type Release struct {
|
|
|
|
|
// Version is the semantic version string (e.g., "v1.2.3").
|
|
|
|
|
Version string
|
|
|
|
|
// Artifacts are the built release artifacts (archives with checksums).
|
|
|
|
|
Artifacts []build.Artifact
|
|
|
|
|
// Changelog is the generated markdown changelog.
|
|
|
|
|
Changelog string
|
|
|
|
|
// ProjectDir is the root directory of the project.
|
|
|
|
|
ProjectDir string
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
// FS is the medium for file operations.
|
|
|
|
|
FS io.Medium
|
2026-01-28 18:33:11 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-29 12:48:28 +00:00
|
|
|
// Publish publishes pre-built artifacts from dist/ to configured targets.
|
|
|
|
|
// Use this after `core build` to separate build and publish concerns.
|
|
|
|
|
// 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")
|
|
|
|
|
}
|
|
|
|
|
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
m := io.Local
|
|
|
|
|
|
2026-01-29 12:48:28 +00:00
|
|
|
projectDir := cfg.projectDir
|
|
|
|
|
if projectDir == "" {
|
|
|
|
|
projectDir = "."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolve to absolute path
|
|
|
|
|
absProjectDir, err := filepath.Abs(projectDir)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("release.Publish: failed to resolve project directory: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 1: Determine version
|
|
|
|
|
version := cfg.version
|
|
|
|
|
if version == "" {
|
|
|
|
|
version, err = DetermineVersion(absProjectDir)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("release.Publish: failed to determine version: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 2: Find pre-built artifacts in dist/
|
|
|
|
|
distDir := filepath.Join(absProjectDir, "dist")
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
artifacts, err := findArtifacts(m, distDir)
|
2026-01-29 12:48:28 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("release.Publish: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(artifacts) == 0 {
|
|
|
|
|
return nil, fmt.Errorf("release.Publish: no artifacts found in dist/\nRun 'core build' first to create artifacts")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 3: Generate changelog
|
|
|
|
|
changelog, err := Generate(absProjectDir, "", version)
|
|
|
|
|
if err != nil {
|
|
|
|
|
// Non-fatal: continue with empty changelog
|
|
|
|
|
changelog = fmt.Sprintf("Release %s", version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
release := &Release{
|
|
|
|
|
Version: version,
|
|
|
|
|
Artifacts: artifacts,
|
|
|
|
|
Changelog: changelog,
|
|
|
|
|
ProjectDir: absProjectDir,
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
FS: m,
|
2026-01-29 12:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 4: Publish to configured targets
|
|
|
|
|
if len(cfg.Publishers) > 0 {
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
pubRelease := publishers.NewRelease(release.Version, release.Artifacts, release.Changelog, release.ProjectDir, release.FS)
|
2026-01-29 12:48:28 +00:00
|
|
|
|
|
|
|
|
for _, pubCfg := range cfg.Publishers {
|
|
|
|
|
publisher, err := getPublisher(pubCfg.Type)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return release, fmt.Errorf("release.Publish: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extendedCfg := buildExtendedConfig(pubCfg)
|
|
|
|
|
publisherCfg := publishers.NewPublisherConfig(pubCfg.Type, pubCfg.Prerelease, pubCfg.Draft, extendedCfg)
|
|
|
|
|
if err := publisher.Publish(ctx, pubRelease, publisherCfg, cfg, dryRun); err != nil {
|
|
|
|
|
return release, fmt.Errorf("release.Publish: publish to %s failed: %w", pubCfg.Type, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return release, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// findArtifacts discovers pre-built artifacts in the dist directory.
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
func findArtifacts(m io.Medium, distDir string) ([]build.Artifact, error) {
|
|
|
|
|
if !m.IsDir(distDir) {
|
2026-01-29 12:48:28 +00:00
|
|
|
return nil, fmt.Errorf("dist/ directory not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var artifacts []build.Artifact
|
|
|
|
|
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
entries, err := m.List(distDir)
|
2026-01-29 12:48:28 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to read dist/: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, entry := range entries {
|
|
|
|
|
if entry.IsDir() {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name := entry.Name()
|
|
|
|
|
path := filepath.Join(distDir, name)
|
|
|
|
|
|
|
|
|
|
// Include archives and checksums
|
|
|
|
|
if strings.HasSuffix(name, ".tar.gz") ||
|
|
|
|
|
strings.HasSuffix(name, ".zip") ||
|
|
|
|
|
strings.HasSuffix(name, ".txt") ||
|
|
|
|
|
strings.HasSuffix(name, ".sig") {
|
|
|
|
|
artifacts = append(artifacts, build.Artifact{Path: path})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return artifacts, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Run executes the full release process: determine version, build artifacts,
|
2026-01-28 18:33:11 +00:00
|
|
|
// generate changelog, and publish to configured targets.
|
2026-01-29 12:48:28 +00:00
|
|
|
// For separated concerns, prefer using `core build` then `core ci` (Publish).
|
2026-01-28 18:33:11 +00:00
|
|
|
// 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")
|
|
|
|
|
}
|
|
|
|
|
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
m := io.Local
|
|
|
|
|
|
2026-01-28 18:33:11 +00:00
|
|
|
projectDir := cfg.projectDir
|
|
|
|
|
if projectDir == "" {
|
|
|
|
|
projectDir = "."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolve to absolute path
|
|
|
|
|
absProjectDir, err := filepath.Abs(projectDir)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("release.Run: failed to resolve project directory: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 1: Determine version
|
|
|
|
|
version := cfg.version
|
|
|
|
|
if version == "" {
|
|
|
|
|
version, err = DetermineVersion(absProjectDir)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("release.Run: failed to determine version: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 2: Generate changelog
|
|
|
|
|
changelog, err := Generate(absProjectDir, "", version)
|
|
|
|
|
if err != nil {
|
|
|
|
|
// Non-fatal: continue with empty changelog
|
|
|
|
|
changelog = fmt.Sprintf("Release %s", version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 3: Build artifacts
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
artifacts, err := buildArtifacts(ctx, m, cfg, absProjectDir, version)
|
2026-01-28 18:33:11 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("release.Run: build failed: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
release := &Release{
|
|
|
|
|
Version: version,
|
|
|
|
|
Artifacts: artifacts,
|
|
|
|
|
Changelog: changelog,
|
|
|
|
|
ProjectDir: absProjectDir,
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
FS: m,
|
2026-01-28 18:33:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 4: Publish to configured targets
|
|
|
|
|
if len(cfg.Publishers) > 0 {
|
|
|
|
|
// Convert to publisher types
|
Migrate pkg/release to io.Medium abstraction (#290)
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
2026-02-04 15:07:13 +00:00
|
|
|
pubRelease := publishers.NewRelease(release.Version, release.Artifacts, release.Changelog, release.ProjectDir, release.FS)
|
2026-01-28 18:33:11 +00:00
|
|
|
|
|
|
|
|
for _, pubCfg := range cfg.Publishers {
|
|
|
|
|
publisher, err := getPublisher(pubCfg.Type)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return release, fmt.Errorf("release.Run: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-28 18:42:04 +00:00
|
|
|
// Build extended config for publisher-specific settings
|
|
|
|
|
extendedCfg := buildExtendedConfig(pubCfg)
|
|
|
|
|
publisherCfg := publishers.NewPublisherConfig(pubCfg.Type, pubCfg.Prerelease, pubCfg.Draft, extendedCfg)
|
2026-01-28 18:33:11 +00:00
|
|
|
if err := publisher.Publish(ctx, pubRelease, publisherCfg, cfg, dryRun); err != nil {
|
|
|
|
|
return release, fmt.Errorf("release.Run: publish to %s failed: %w", pubCfg.Type, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return release, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// buildArtifacts builds all artifacts for the release.
|
2026-02-04 17:59:10 +00:00
|
|
|
func buildArtifacts(ctx context.Context, fs io.Medium, cfg *Config, projectDir, version string) ([]build.Artifact, error) {
|
2026-01-28 18:33:11 +00:00
|
|
|
// Load build configuration
|
2026-02-04 17:59:10 +00:00
|
|
|
buildCfg, err := build.LoadConfig(fs, projectDir)
|
2026-01-28 18:33:11 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to load build config: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine targets
|
|
|
|
|
var targets []build.Target
|
|
|
|
|
if len(cfg.Build.Targets) > 0 {
|
|
|
|
|
for _, t := range cfg.Build.Targets {
|
|
|
|
|
targets = append(targets, build.Target{OS: t.OS, Arch: t.Arch})
|
|
|
|
|
}
|
|
|
|
|
} else if len(buildCfg.Targets) > 0 {
|
|
|
|
|
targets = buildCfg.ToTargets()
|
|
|
|
|
} else {
|
|
|
|
|
// Default targets
|
|
|
|
|
targets = []build.Target{
|
|
|
|
|
{OS: "linux", Arch: "amd64"},
|
|
|
|
|
{OS: "linux", Arch: "arm64"},
|
|
|
|
|
{OS: "darwin", Arch: "arm64"},
|
|
|
|
|
{OS: "windows", Arch: "amd64"},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine binary name
|
|
|
|
|
binaryName := cfg.Project.Name
|
|
|
|
|
if binaryName == "" {
|
|
|
|
|
binaryName = buildCfg.Project.Binary
|
|
|
|
|
}
|
|
|
|
|
if binaryName == "" {
|
|
|
|
|
binaryName = buildCfg.Project.Name
|
|
|
|
|
}
|
|
|
|
|
if binaryName == "" {
|
|
|
|
|
binaryName = filepath.Base(projectDir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine output directory
|
|
|
|
|
outputDir := filepath.Join(projectDir, "dist")
|
|
|
|
|
|
|
|
|
|
// Get builder (detect project type)
|
2026-02-04 17:59:10 +00:00
|
|
|
projectType, err := build.PrimaryType(fs, projectDir)
|
2026-01-28 18:33:11 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to detect project type: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
builder, err := getBuilder(projectType)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build configuration
|
|
|
|
|
buildConfig := &build.Config{
|
2026-02-04 17:59:10 +00:00
|
|
|
FS: fs,
|
2026-01-28 18:33:11 +00:00
|
|
|
ProjectDir: projectDir,
|
|
|
|
|
OutputDir: outputDir,
|
|
|
|
|
Name: binaryName,
|
|
|
|
|
Version: version,
|
|
|
|
|
LDFlags: buildCfg.Build.LDFlags,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build
|
|
|
|
|
artifacts, err := builder.Build(ctx, buildConfig, targets)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("build failed: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Archive artifacts
|
2026-02-04 17:59:10 +00:00
|
|
|
archivedArtifacts, err := build.ArchiveAll(fs, artifacts)
|
2026-01-28 18:33:11 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("archive failed: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute checksums
|
2026-02-04 17:59:10 +00:00
|
|
|
checksummedArtifacts, err := build.ChecksumAll(fs, archivedArtifacts)
|
2026-01-28 18:33:11 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("checksum failed: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write CHECKSUMS.txt
|
|
|
|
|
checksumPath := filepath.Join(outputDir, "CHECKSUMS.txt")
|
2026-02-04 17:59:10 +00:00
|
|
|
if err := build.WriteChecksumFile(fs, checksummedArtifacts, checksumPath); err != nil {
|
2026-01-28 18:33:11 +00:00
|
|
|
return nil, fmt.Errorf("failed to write checksums file: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add CHECKSUMS.txt as an artifact
|
|
|
|
|
checksumArtifact := build.Artifact{
|
|
|
|
|
Path: checksumPath,
|
|
|
|
|
}
|
|
|
|
|
checksummedArtifacts = append(checksummedArtifacts, checksumArtifact)
|
|
|
|
|
|
|
|
|
|
return checksummedArtifacts, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getBuilder returns the appropriate builder for the project type.
|
|
|
|
|
func getBuilder(projectType build.ProjectType) (build.Builder, error) {
|
|
|
|
|
switch projectType {
|
|
|
|
|
case build.ProjectTypeWails:
|
|
|
|
|
return builders.NewWailsBuilder(), nil
|
|
|
|
|
case build.ProjectTypeGo:
|
|
|
|
|
return builders.NewGoBuilder(), nil
|
|
|
|
|
case build.ProjectTypeNode:
|
feat: infrastructure packages and lint cleanup (#281)
* ci: consolidate duplicate workflows and merge CodeQL configs
Remove 17 duplicate workflow files that were split copies of the
combined originals. Each family (CI, CodeQL, Coverage, PR Build,
Alpha Release) had the same job duplicated across separate
push/pull_request/schedule/manual trigger files.
Merge codeql.yml and codescan.yml into a single codeql.yml with
a language matrix covering go, javascript-typescript, python,
and actions — matching the previous default setup coverage.
Remaining workflows (one per family):
- ci.yml (push + PR + manual)
- codeql.yml (push + PR + schedule, all languages)
- coverage.yml (push + PR + manual)
- alpha-release.yml (push + manual)
- pr-build.yml (PR + manual)
- release.yml (tag push)
- agent-verify.yml, auto-label.yml, auto-project.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add collect, config, crypt, plugin packages and fix all lint issues
Add four new infrastructure packages with CLI commands:
- pkg/config: layered configuration (defaults → file → env → flags)
- pkg/crypt: crypto primitives (Argon2id, AES-GCM, ChaCha20, HMAC, checksums)
- pkg/plugin: plugin system with GitHub-based install/update/remove
- pkg/collect: collection subsystem (GitHub, BitcoinTalk, market, papers, excavate)
Fix all golangci-lint issues across the entire codebase (~100 errcheck,
staticcheck SA1012/SA1019/ST1005, unused, ineffassign fixes) so that
`core go qa` passes with 0 issues.
Closes #167, #168, #170, #250, #251, #252, #253, #254, #255, #256
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:34:43 +00:00
|
|
|
return nil, fmt.Errorf("node.js builder not yet implemented")
|
2026-01-28 18:33:11 +00:00
|
|
|
case build.ProjectTypePHP:
|
|
|
|
|
return nil, fmt.Errorf("PHP builder not yet implemented")
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("unsupported project type: %s", projectType)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getPublisher returns the publisher for the given type.
|
|
|
|
|
func getPublisher(pubType string) (publishers.Publisher, error) {
|
|
|
|
|
switch pubType {
|
|
|
|
|
case "github":
|
|
|
|
|
return publishers.NewGitHubPublisher(), nil
|
2026-01-28 18:42:04 +00:00
|
|
|
case "linuxkit":
|
|
|
|
|
return publishers.NewLinuxKitPublisher(), nil
|
|
|
|
|
case "docker":
|
|
|
|
|
return publishers.NewDockerPublisher(), nil
|
2026-01-29 00:32:04 +00:00
|
|
|
case "npm":
|
|
|
|
|
return publishers.NewNpmPublisher(), nil
|
|
|
|
|
case "homebrew":
|
|
|
|
|
return publishers.NewHomebrewPublisher(), nil
|
|
|
|
|
case "scoop":
|
|
|
|
|
return publishers.NewScoopPublisher(), nil
|
|
|
|
|
case "aur":
|
|
|
|
|
return publishers.NewAURPublisher(), nil
|
|
|
|
|
case "chocolatey":
|
|
|
|
|
return publishers.NewChocolateyPublisher(), nil
|
2026-01-28 18:33:11 +00:00
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("unsupported publisher type: %s", pubType)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-28 18:42:04 +00:00
|
|
|
|
|
|
|
|
// buildExtendedConfig builds a map of extended configuration for a publisher.
|
|
|
|
|
func buildExtendedConfig(pubCfg PublisherConfig) map[string]any {
|
|
|
|
|
ext := make(map[string]any)
|
|
|
|
|
|
|
|
|
|
// LinuxKit-specific config
|
|
|
|
|
if pubCfg.Config != "" {
|
|
|
|
|
ext["config"] = pubCfg.Config
|
|
|
|
|
}
|
|
|
|
|
if len(pubCfg.Formats) > 0 {
|
|
|
|
|
ext["formats"] = toAnySlice(pubCfg.Formats)
|
|
|
|
|
}
|
|
|
|
|
if len(pubCfg.Platforms) > 0 {
|
|
|
|
|
ext["platforms"] = toAnySlice(pubCfg.Platforms)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Docker-specific config
|
|
|
|
|
if pubCfg.Registry != "" {
|
|
|
|
|
ext["registry"] = pubCfg.Registry
|
|
|
|
|
}
|
|
|
|
|
if pubCfg.Image != "" {
|
|
|
|
|
ext["image"] = pubCfg.Image
|
|
|
|
|
}
|
|
|
|
|
if pubCfg.Dockerfile != "" {
|
|
|
|
|
ext["dockerfile"] = pubCfg.Dockerfile
|
|
|
|
|
}
|
|
|
|
|
if len(pubCfg.Tags) > 0 {
|
|
|
|
|
ext["tags"] = toAnySlice(pubCfg.Tags)
|
|
|
|
|
}
|
|
|
|
|
if len(pubCfg.BuildArgs) > 0 {
|
|
|
|
|
args := make(map[string]any)
|
|
|
|
|
for k, v := range pubCfg.BuildArgs {
|
|
|
|
|
args[k] = v
|
|
|
|
|
}
|
|
|
|
|
ext["build_args"] = args
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-29 00:32:04 +00:00
|
|
|
// npm-specific config
|
|
|
|
|
if pubCfg.Package != "" {
|
|
|
|
|
ext["package"] = pubCfg.Package
|
|
|
|
|
}
|
|
|
|
|
if pubCfg.Access != "" {
|
|
|
|
|
ext["access"] = pubCfg.Access
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Homebrew-specific config
|
|
|
|
|
if pubCfg.Tap != "" {
|
|
|
|
|
ext["tap"] = pubCfg.Tap
|
|
|
|
|
}
|
|
|
|
|
if pubCfg.Formula != "" {
|
|
|
|
|
ext["formula"] = pubCfg.Formula
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Scoop-specific config
|
|
|
|
|
if pubCfg.Bucket != "" {
|
|
|
|
|
ext["bucket"] = pubCfg.Bucket
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AUR-specific config
|
|
|
|
|
if pubCfg.Maintainer != "" {
|
|
|
|
|
ext["maintainer"] = pubCfg.Maintainer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Chocolatey-specific config
|
|
|
|
|
if pubCfg.Push {
|
|
|
|
|
ext["push"] = pubCfg.Push
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Official repo config (shared by multiple publishers)
|
|
|
|
|
if pubCfg.Official != nil {
|
|
|
|
|
official := make(map[string]any)
|
|
|
|
|
official["enabled"] = pubCfg.Official.Enabled
|
|
|
|
|
if pubCfg.Official.Output != "" {
|
|
|
|
|
official["output"] = pubCfg.Official.Output
|
|
|
|
|
}
|
|
|
|
|
ext["official"] = official
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-28 18:42:04 +00:00
|
|
|
return ext
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// toAnySlice converts a string slice to an any slice.
|
|
|
|
|
func toAnySlice(s []string) []any {
|
|
|
|
|
result := make([]any, len(s))
|
|
|
|
|
for i, v := range s {
|
|
|
|
|
result[i] = v
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|