From 63967eb6fa94846f777505d7dedeb50f2b8e9f2c Mon Sep 17 00:00:00 2001 From: logikonline Date: Mon, 19 Jan 2026 01:16:47 -0500 Subject: [PATCH] style(ui): add package docs and mark unused parameters Adds package-level documentation comments across cmd and internal packages. Marks unused function parameters with underscore prefix to satisfy linter requirements. Replaces if-else chains with switch statements for better readability. Explicitly ignores os.Setenv return value where error handling is not needed. --- cmd/upload-helper/main.go | 1 + internal/app/cmd/cache-server.go | 4 +- internal/app/cmd/cmd.go | 2 + internal/app/cmd/daemon.go | 28 ++-- internal/app/cmd/exec.go | 24 ++-- internal/app/cmd/register.go | 7 +- internal/app/poll/poller.go | 16 ++- internal/app/run/logging.go | 1 + internal/app/run/runner.go | 13 +- internal/pkg/artifact/upload_helper.go | 9 +- internal/pkg/client/client.go | 1 + internal/pkg/client/header.go | 1 + internal/pkg/client/http.go | 2 + internal/pkg/config/config.go | 1 + internal/pkg/config/embed.go | 2 + internal/pkg/config/registration.go | 6 +- internal/pkg/envcheck/bandwidth.go | 4 +- internal/pkg/envcheck/capabilities.go | 172 ++++++++++++------------- internal/pkg/envcheck/docker.go | 3 +- internal/pkg/labels/labels.go | 9 ++ internal/pkg/report/reporter.go | 14 +- internal/pkg/ver/version.go | 2 + main.go | 1 + 23 files changed, 183 insertions(+), 140 deletions(-) diff --git a/cmd/upload-helper/main.go b/cmd/upload-helper/main.go index fa6588e..937b026 100644 --- a/cmd/upload-helper/main.go +++ b/cmd/upload-helper/main.go @@ -1,6 +1,7 @@ // Copyright 2026 MarketAlly. All rights reserved. // SPDX-License-Identifier: MIT +// Package main provides the upload-helper CLI tool for reliable file uploads. package main import ( diff --git a/internal/app/cmd/cache-server.go b/internal/app/cmd/cache-server.go index 98aaaec..726ad9c 100644 --- a/internal/app/cmd/cache-server.go +++ b/internal/app/cmd/cache-server.go @@ -22,8 +22,8 @@ type cacheServerArgs struct { Port uint16 } -func runCacheServer(ctx context.Context, configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { +func runCacheServer(_ context.Context, configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error { + return func(_ *cobra.Command, _ []string) error { cfg, err := config.LoadDefault(*configFile) if err != nil { return fmt.Errorf("invalid configuration: %w", err) diff --git a/internal/app/cmd/cmd.go b/internal/app/cmd/cmd.go index 62cf431..b2aec1d 100644 --- a/internal/app/cmd/cmd.go +++ b/internal/app/cmd/cmd.go @@ -1,6 +1,7 @@ // Copyright 2022 The Gitea Authors and MarketAlly. All rights reserved. // SPDX-License-Identifier: MIT +// Package cmd provides the CLI commands for gitcaddy-runner. package cmd import ( @@ -15,6 +16,7 @@ import ( "git.marketally.com/gitcaddy/gitcaddy-runner/internal/pkg/ver" ) +// Execute runs the root command for gitcaddy-runner CLI. func Execute(ctx context.Context) { // ./gitcaddy-runner rootCmd := &cobra.Command{ diff --git a/internal/app/cmd/daemon.go b/internal/app/cmd/daemon.go index a9a6189..0c31c42 100644 --- a/internal/app/cmd/daemon.go +++ b/internal/app/cmd/daemon.go @@ -58,7 +58,7 @@ var ( ) func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { + return func(_ *cobra.Command, _ []string) error { cfg, err := config.LoadDefault(*configFile) if err != nil { return fmt.Errorf("invalid configuration: %w", err) @@ -132,7 +132,7 @@ func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) fu return err } // if dockerSocketPath passes the check, override DOCKER_HOST with dockerSocketPath - os.Setenv("DOCKER_HOST", dockerSocketPath) + _ = os.Setenv("DOCKER_HOST", dockerSocketPath) // empty cfg.Container.DockerHost means act_runner need to find an available docker host automatically // and assign the path to cfg.Container.DockerHost if cfg.Container.DockerHost == "" { @@ -182,21 +182,22 @@ func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) fu capabilities := envcheck.DetectCapabilities(ctx, dockerHost, cfg.Container.WorkdirParent, globalConfig.Runner.Capacity) // Include initial bandwidth result if available capabilities.Bandwidth = bandwidthManager.GetLastResult() - capabilitiesJson := capabilities.ToJSON() - log.Infof("detected capabilities: %s", capabilitiesJson) + capabilitiesJSON := capabilities.ToJSON() + log.Infof("detected capabilities: %s", capabilitiesJSON) // Check disk space and warn if low checkDiskSpaceAndCleanup(ctx, capabilities) // declare the labels of the runner before fetching tasks - resp, err := runner.Declare(ctx, ls.Names(), capabilitiesJson) - if err != nil && connect.CodeOf(err) == connect.CodeUnimplemented { + resp, err := runner.Declare(ctx, ls.Names(), capabilitiesJSON) + switch { + case err != nil && connect.CodeOf(err) == connect.CodeUnimplemented: log.Errorf("Your GitCaddy version is too old to support runner declare, please upgrade to v1.21 or later") return err - } else if err != nil { + case err != nil: log.WithError(err).Error("fail to invoke Declare") return err - } else { + default: log.Infof("runner: %s, with version: %s, with labels: %v, declare successfully", resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels) } @@ -261,14 +262,15 @@ func checkDiskSpaceAndCleanup(ctx context.Context, capabilities *envcheck.Runner usedPercent := capabilities.Disk.UsedPercent freeGB := float64(capabilities.Disk.Free) / (1024 * 1024 * 1024) - if usedPercent >= DiskSpaceCriticalThreshold { + switch { + case usedPercent >= DiskSpaceCriticalThreshold: log.Errorf("CRITICAL: Disk space critically low! %.1f%% used, only %.2f GB free. Runner may fail to execute jobs!", usedPercent, freeGB) // Always try cleanup at critical level triggerAutoCleanup(ctx) - } else if usedPercent >= DiskSpaceAutoCleanupThreshold { + case usedPercent >= DiskSpaceAutoCleanupThreshold: log.Warnf("WARNING: Disk space at %.1f%% used (%.2f GB free). Triggering automatic cleanup.", usedPercent, freeGB) triggerAutoCleanup(ctx) - } else if usedPercent >= DiskSpaceWarningThreshold { + case usedPercent >= DiskSpaceWarningThreshold: log.Warnf("WARNING: Disk space running low. %.1f%% used, %.2f GB free. Consider cleaning up disk space.", usedPercent, freeGB) } } @@ -330,13 +332,13 @@ func periodicCapabilitiesUpdate(ctx context.Context, runner *run.Runner, labelNa capabilities.Bandwidth = bandwidthManager.GetLastResult() } - capabilitiesJson := capabilities.ToJSON() + capabilitiesJSON := capabilities.ToJSON() // Check for disk space warnings checkDiskSpaceAndCleanup(ctx, capabilities) // Send updated capabilities to server - _, err := runner.Declare(ctx, labelNames, capabilitiesJson) + _, err := runner.Declare(ctx, labelNames, capabilitiesJSON) if err != nil { log.WithError(err).Debug("failed to update capabilities") } else { diff --git a/internal/app/cmd/exec.go b/internal/app/cmd/exec.go index 8ed010d..b655bdb 100644 --- a/internal/app/cmd/exec.go +++ b/internal/app/cmd/exec.go @@ -264,7 +264,7 @@ func printList(plan *model.Plan) error { return nil } -func runExecList(ctx context.Context, planner model.WorkflowPlanner, execArgs *executeArgs) error { +func runExecList(_ context.Context, planner model.WorkflowPlanner, execArgs *executeArgs) error { // plan with filtered jobs - to be used for filtering only var filterPlan *model.Plan @@ -286,19 +286,20 @@ func runExecList(ctx context.Context, planner model.WorkflowPlanner, execArgs *e } var err error - if execArgs.job != "" { + switch { + case execArgs.job != "": log.Infof("Preparing plan with a job: %s", execArgs.job) filterPlan, err = planner.PlanJob(execArgs.job) if err != nil { return err } - } else if filterEventName != "" { + case filterEventName != "": log.Infof("Preparing plan for a event: %s", filterEventName) filterPlan, err = planner.PlanEvent(filterEventName) if err != nil { return err } - } else { + default: log.Infof("Preparing plan with all jobs") filterPlan, err = planner.PlanAll() if err != nil { @@ -312,7 +313,7 @@ func runExecList(ctx context.Context, planner model.WorkflowPlanner, execArgs *e } func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { + return func(_ *cobra.Command, _ []string) error { planner, err := model.NewWorkflowPlanner(execArgs.WorkflowsPath(), execArgs.noWorkflowRecurse) if err != nil { return err @@ -331,18 +332,19 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command // collect all events from loaded workflows events := planner.GetEvents() - if len(execArgs.event) > 0 { + switch { + case len(execArgs.event) > 0: log.Infof("Using chosed event for filtering: %s", execArgs.event) eventName = execArgs.event - } else if len(events) == 1 && len(events[0]) > 0 { + case len(events) == 1 && len(events[0]) > 0: log.Infof("Using the only detected workflow event: %s", events[0]) eventName = events[0] - } else if execArgs.autodetectEvent && len(events) > 0 && len(events[0]) > 0 { + case execArgs.autodetectEvent && len(events) > 0 && len(events[0]) > 0: // set default event type to first event from many available // this way user dont have to specify the event. log.Infof("Using first detected workflow event: %s", events[0]) eventName = events[0] - } else { + default: log.Infof("Using default workflow event: push") eventName = "push" } @@ -388,7 +390,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command if err != nil { fmt.Println(err) } - defer os.RemoveAll(tempDir) + defer func() { _ = os.RemoveAll(tempDir) }() execArgs.artifactServerPath = tempDir } @@ -454,7 +456,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command log.Debugf("artifacts server started at %s:%s", execArgs.artifactServerPath, execArgs.artifactServerPort) ctx = common.WithDryrun(ctx, execArgs.dryrun) - executor := r.NewPlanExecutor(plan).Finally(func(ctx context.Context) error { + executor := r.NewPlanExecutor(plan).Finally(func(_ context.Context) error { artifactCancel() return nil }) diff --git a/internal/app/cmd/register.go b/internal/app/cmd/register.go index 5b05bca..9fefcf0 100644 --- a/internal/app/cmd/register.go +++ b/internal/app/cmd/register.go @@ -28,7 +28,7 @@ import ( // runRegister registers a runner to the server func runRegister(ctx context.Context, regArgs *registerArgs, configFile *string) func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { + return func(_ *cobra.Command, _ []string) error { log.SetReportCaller(false) isTerm := isatty.IsTerminal(os.Stdout.Fd()) log.SetFormatter(&log.TextFormatter{ @@ -80,6 +80,7 @@ type registerArgs struct { type registerStage int8 +// Register stage constants define the steps in the registration workflow. const ( StageUnknown registerStage = -1 StageOverwriteLocalConfig registerStage = iota + 1 @@ -250,7 +251,7 @@ func registerInteractive(ctx context.Context, configFile string, regArgs *regist if stage == StageWaitingForRegistration { log.Infof("Registering runner, name=%s, instance=%s, labels=%v.", inputs.RunnerName, inputs.InstanceAddr, inputs.Labels) if err := doRegister(ctx, cfg, inputs); err != nil { - return fmt.Errorf("Failed to register runner: %w", err) + return fmt.Errorf("failed to register runner: %w", err) } log.Infof("Runner registered successfully.") return nil @@ -311,7 +312,7 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi return err } if err := doRegister(ctx, cfg, inputs); err != nil { - return fmt.Errorf("Failed to register runner: %w", err) + return fmt.Errorf("failed to register runner: %w", err) } log.Infof("Runner registered successfully.") return nil diff --git a/internal/app/poll/poller.go b/internal/app/poll/poller.go index 1d96b53..c08e004 100644 --- a/internal/app/poll/poller.go +++ b/internal/app/poll/poller.go @@ -1,6 +1,7 @@ // Copyright 2023 The Gitea Authors and MarketAlly. All rights reserved. // SPDX-License-Identifier: MIT +// Package poll provides task polling functionality for CI runners. package poll import ( @@ -22,6 +23,7 @@ import ( "git.marketally.com/gitcaddy/gitcaddy-runner/internal/pkg/envcheck" ) +// Poller handles task polling from the Gitea server. type Poller struct { client client.Client runner *run.Runner @@ -38,6 +40,7 @@ type Poller struct { done chan struct{} } +// New creates a new Poller instance. func New(cfg *config.Config, client client.Client, runner *run.Runner) *Poller { pollingCtx, shutdownPolling := context.WithCancel(context.Background()) @@ -65,6 +68,7 @@ func (p *Poller) SetBandwidthManager(bm *envcheck.BandwidthManager) { p.bandwidthManager = bm } +// Poll starts polling for tasks with the configured capacity. func (p *Poller) Poll() { limiter := rate.NewLimiter(rate.Every(p.cfg.Runner.FetchInterval), 1) wg := &sync.WaitGroup{} @@ -78,6 +82,7 @@ func (p *Poller) Poll() { close(p.done) } +// PollOnce polls for a single task and then exits. func (p *Poller) PollOnce() { limiter := rate.NewLimiter(rate.Every(p.cfg.Runner.FetchInterval), 1) @@ -87,18 +92,19 @@ func (p *Poller) PollOnce() { close(p.done) } +// Shutdown gracefully stops the poller. func (p *Poller) Shutdown(ctx context.Context) error { p.shutdownPolling() select { - // graceful shutdown completed succesfully + // graceful shutdown completed successfully case <-p.done: return nil // our timeout for shutting down ran out case <-ctx.Done(): // when both the timeout fires and the graceful shutdown - // completed succsfully, this branch of the select may + // completed successfully, this branch of the select may // fire. Do a non-blocking check here against the graceful // shutdown status to avoid sending an error if we don't need to. _, ok := <-p.done @@ -110,7 +116,7 @@ func (p *Poller) Shutdown(ctx context.Context) error { p.shutdownJobs() // wait for running jobs to report their status to Gitea - _, _ = <-p.done + <-p.done return ctx.Err() } @@ -173,13 +179,13 @@ func (p *Poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) { caps.Bandwidth = p.bandwidthManager.GetLastResult() } - capsJson := caps.ToJSON() + capsJSON := caps.ToJSON() // Load the version value that was in the cache when the request was sent. v := p.tasksVersion.Load() fetchReq := &runnerv1.FetchTaskRequest{ TasksVersion: v, - CapabilitiesJson: capsJson, + CapabilitiesJson: capsJSON, } resp, err := p.client.FetchTask(reqCtx, connect.NewRequest(fetchReq)) if errors.Is(err, context.DeadlineExceeded) { diff --git a/internal/app/run/logging.go b/internal/app/run/logging.go index d0e6d1c..68071a1 100644 --- a/internal/app/run/logging.go +++ b/internal/app/run/logging.go @@ -1,6 +1,7 @@ // Copyright 2024 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// Package run provides the core runner functionality for executing tasks. package run import ( diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index 77c74e2..34d4040 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -85,6 +85,7 @@ func (r *Runner) CleanStaleJobCaches(maxAge time.Duration) { } } +// NewRunner creates a new Runner with the given configuration, registration, and client. func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) *Runner { ls := labels.Labels{} for _, v := range reg.Labels { @@ -133,6 +134,7 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) } } +// Run executes a task from the server. func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error { if _, ok := r.runningTasks.Load(task.Id); ok { return fmt.Errorf("task %d is already running", task.Id) @@ -161,7 +163,7 @@ func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error { // getDefaultActionsURL // when DEFAULT_ACTIONS_URL == "https://github.com" and GithubMirror is not blank, // it should be set to GithubMirror first. -func (r *Runner) getDefaultActionsURL(ctx context.Context, task *runnerv1.Task) string { +func (r *Runner) getDefaultActionsURL(_ context.Context, task *runnerv1.Task) string { giteaDefaultActionsURL := task.Context.Fields["gitea_default_actions_url"].GetStringValue() if giteaDefaultActionsURL == "https://github.com" && r.cfg.Runner.GithubMirror != "" { return r.cfg.Runner.GithubMirror @@ -219,8 +221,8 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. preset.Token = t } - if actionsIdTokenRequestUrl := taskContext["actions_id_token_request_url"].GetStringValue(); actionsIdTokenRequestUrl != "" { - r.envs["ACTIONS_ID_TOKEN_REQUEST_URL"] = actionsIdTokenRequestUrl + if actionsIDTokenRequestURL := taskContext["actions_id_token_request_url"].GetStringValue(); actionsIDTokenRequestURL != "" { + r.envs["ACTIONS_ID_TOKEN_REQUEST_URL"] = actionsIDTokenRequestURL r.envs["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = taskContext["actions_id_token_request_token"].GetStringValue() task.Secrets["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = r.envs["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] } @@ -305,10 +307,11 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. return execErr } -func (r *Runner) Declare(ctx context.Context, labels []string, capabilitiesJson string) (*connect.Response[runnerv1.DeclareResponse], error) { +// Declare sends the runner's labels and capabilities to the server. +func (r *Runner) Declare(ctx context.Context, labels []string, capabilitiesJSON string) (*connect.Response[runnerv1.DeclareResponse], error) { return r.client.Declare(ctx, connect.NewRequest(&runnerv1.DeclareRequest{ Version: ver.Version(), Labels: labels, - CapabilitiesJson: capabilitiesJson, + CapabilitiesJson: capabilitiesJSON, })) } diff --git a/internal/pkg/artifact/upload_helper.go b/internal/pkg/artifact/upload_helper.go index a0dee9e..08b335f 100644 --- a/internal/pkg/artifact/upload_helper.go +++ b/internal/pkg/artifact/upload_helper.go @@ -1,6 +1,7 @@ // Copyright 2026 MarketAlly. All rights reserved. // SPDX-License-Identifier: MIT +// Package artifact provides utilities for handling artifact uploads. package artifact import ( @@ -88,7 +89,7 @@ func (u *UploadHelper) prewarmConnection(url string) error { if err != nil { return err } - resp.Body.Close() + _ = resp.Body.Close() return nil } @@ -98,7 +99,7 @@ func (u *UploadHelper) doUpload(client *http.Client, url, token, filepath string if err != nil { return fmt.Errorf("failed to open file: %w", err) } - defer file.Close() + defer func() { _ = file.Close() }() stat, err := file.Stat() if err != nil { @@ -118,7 +119,7 @@ func (u *UploadHelper) doUpload(client *http.Client, url, token, filepath string if _, err := io.Copy(part, file); err != nil { return fmt.Errorf("failed to copy file to form: %w", err) } - writer.Close() + _ = writer.Close() req, err := http.NewRequest("POST", url, body) if err != nil { @@ -133,7 +134,7 @@ func (u *UploadHelper) doUpload(client *http.Client, url, token, filepath string if err != nil { return fmt.Errorf("upload request failed: %w", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() if resp.StatusCode < 200 || resp.StatusCode >= 300 { respBody, _ := io.ReadAll(resp.Body) diff --git a/internal/pkg/client/client.go b/internal/pkg/client/client.go index 57f91ad..5744ccf 100644 --- a/internal/pkg/client/client.go +++ b/internal/pkg/client/client.go @@ -1,6 +1,7 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// Package client provides the HTTP client for communicating with the runner API. package client import ( diff --git a/internal/pkg/client/header.go b/internal/pkg/client/header.go index 24844fa..5bf2fab 100644 --- a/internal/pkg/client/header.go +++ b/internal/pkg/client/header.go @@ -3,6 +3,7 @@ package client +// HTTP header constants for runner authentication and identification. const ( UUIDHeader = "x-runner-uuid" TokenHeader = "x-runner-token" diff --git a/internal/pkg/client/http.go b/internal/pkg/client/http.go index d365a77..65529cc 100644 --- a/internal/pkg/client/http.go +++ b/internal/pkg/client/http.go @@ -63,10 +63,12 @@ func New(endpoint string, insecure bool, uuid, token, version string, opts ...co } } +// Address returns the endpoint URL of the client. func (c *HTTPClient) Address() string { return c.endpoint } +// Insecure returns whether TLS verification is disabled. func (c *HTTPClient) Insecure() bool { return c.insecure } diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 93e8206..1bb6b8b 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -1,6 +1,7 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// Package config provides configuration loading and management for the runner. package config import ( diff --git a/internal/pkg/config/embed.go b/internal/pkg/config/embed.go index cf445cf..6ea3641 100644 --- a/internal/pkg/config/embed.go +++ b/internal/pkg/config/embed.go @@ -5,5 +5,7 @@ package config import _ "embed" +// Example contains the example configuration file content. +// //go:embed config.example.yaml var Example []byte diff --git a/internal/pkg/config/registration.go b/internal/pkg/config/registration.go index 414f44f..1d06dab 100644 --- a/internal/pkg/config/registration.go +++ b/internal/pkg/config/registration.go @@ -23,12 +23,13 @@ type Registration struct { Ephemeral bool `json:"ephemeral"` } +// LoadRegistration loads the runner registration from a JSON file. func LoadRegistration(file string) (*Registration, error) { f, err := os.Open(file) if err != nil { return nil, err } - defer f.Close() + defer func() { _ = f.Close() }() var reg Registration if err := json.NewDecoder(f).Decode(®); err != nil { @@ -40,12 +41,13 @@ func LoadRegistration(file string) (*Registration, error) { return ®, nil } +// SaveRegistration saves the runner registration to a JSON file. func SaveRegistration(file string, reg *Registration) error { f, err := os.Create(file) if err != nil { return err } - defer f.Close() + defer func() { _ = f.Close() }() reg.Warning = registrationWarning diff --git a/internal/pkg/envcheck/bandwidth.go b/internal/pkg/envcheck/bandwidth.go index 765d4b0..3c0bf22 100644 --- a/internal/pkg/envcheck/bandwidth.go +++ b/internal/pkg/envcheck/bandwidth.go @@ -121,7 +121,7 @@ func testLatency(ctx context.Context, serverURL string) float64 { if err != nil { return 0 } - resp.Body.Close() + _ = resp.Body.Close() latency := time.Since(start).Seconds() * 1000 // Convert to ms return float64(int(latency*100)) / 100 // Round to 2 decimals @@ -169,7 +169,7 @@ func testDownloadSpeed(ctx context.Context, serverURL string) float64 { } n, _ := io.Copy(io.Discard, resp.Body) - resp.Body.Close() + _ = resp.Body.Close() cancel() duration := time.Since(start) diff --git a/internal/pkg/envcheck/capabilities.go b/internal/pkg/envcheck/capabilities.go index 8812f99..cfc63d0 100644 --- a/internal/pkg/envcheck/capabilities.go +++ b/internal/pkg/envcheck/capabilities.go @@ -83,7 +83,7 @@ type CapabilityFeatures struct { // DetectCapabilities detects the runner's capabilities // workingDir is the directory where builds will run (for disk space detection) func DetectCapabilities(ctx context.Context, dockerHost string, workingDir string, capacity int) *RunnerCapabilities { - cap := &RunnerCapabilities{ + caps := &RunnerCapabilities{ Capacity: capacity, OS: runtime.GOOS, Arch: runtime.GOARCH, @@ -105,40 +105,40 @@ func DetectCapabilities(ctx context.Context, dockerHost string, workingDir strin // Detect Linux distribution if runtime.GOOS == "linux" { - cap.Distro = detectLinuxDistro() + caps.Distro = detectLinuxDistro() } // Detect macOS Xcode/iOS if runtime.GOOS == "darwin" { - cap.Xcode = detectXcode(ctx) + caps.Xcode = detectXcode(ctx) } // Detect Docker - cap.Docker, cap.ContainerRuntime = detectDocker(ctx, dockerHost) - if cap.Docker { - cap.DockerCompose = detectDockerCompose(ctx) - cap.Features.Services = true + caps.Docker, caps.ContainerRuntime = detectDocker(ctx, dockerHost) + if caps.Docker { + caps.DockerCompose = detectDockerCompose(ctx) + caps.Features.Services = true } // Detect common tools - detectTools(ctx, cap) + detectTools(ctx, caps) // Detect build tools - detectBuildTools(ctx, cap) + detectBuildTools(ctx, caps) // Detect package managers - detectPackageManagers(ctx, cap) + detectPackageManagers(ctx, caps) // Detect disk space on the working directory's filesystem - cap.Disk = detectDiskSpace(workingDir) + caps.Disk = detectDiskSpace(workingDir) // Detect CPU load - cap.CPU = detectCPULoad() + caps.CPU = detectCPULoad() // Generate suggested labels based on detected capabilities - cap.SuggestedLabels = generateSuggestedLabels(cap) + caps.SuggestedLabels = generateSuggestedLabels(caps) - return cap + return caps } // detectXcode detects Xcode and iOS development capabilities on macOS @@ -227,18 +227,19 @@ func detectLinuxDistro() *DistroInfo { if err != nil { return nil } - defer file.Close() + defer func() { _ = file.Close() }() distro := &DistroInfo{} scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() - if strings.HasPrefix(line, "ID=") { + switch { + case strings.HasPrefix(line, "ID="): distro.ID = strings.Trim(strings.TrimPrefix(line, "ID="), "\"") - } else if strings.HasPrefix(line, "VERSION_ID=") { + case strings.HasPrefix(line, "VERSION_ID="): distro.VersionID = strings.Trim(strings.TrimPrefix(line, "VERSION_ID="), "\"") - } else if strings.HasPrefix(line, "PRETTY_NAME=") { + case strings.HasPrefix(line, "PRETTY_NAME="): distro.PrettyName = strings.Trim(strings.TrimPrefix(line, "PRETTY_NAME="), "\"") } } @@ -251,7 +252,7 @@ func detectLinuxDistro() *DistroInfo { } // generateSuggestedLabels creates industry-standard labels based on capabilities -func generateSuggestedLabels(cap *RunnerCapabilities) []string { +func generateSuggestedLabels(caps *RunnerCapabilities) []string { labels := []string{} seen := make(map[string]bool) @@ -263,7 +264,7 @@ func generateSuggestedLabels(cap *RunnerCapabilities) []string { } // OS labels - switch cap.OS { + switch caps.OS { case "linux": addLabel("linux") addLabel("linux-latest") @@ -276,17 +277,17 @@ func generateSuggestedLabels(cap *RunnerCapabilities) []string { } // Distro labels (Linux only) - if cap.Distro != nil && cap.Distro.ID != "" { - distro := strings.ToLower(cap.Distro.ID) + if caps.Distro != nil && caps.Distro.ID != "" { + distro := strings.ToLower(caps.Distro.ID) addLabel(distro) addLabel(distro + "-latest") } // Xcode/iOS labels (macOS only) - if cap.Xcode != nil { + if caps.Xcode != nil { addLabel("xcode") // Check for SDKs - for _, sdk := range cap.Xcode.SDKs { + for _, sdk := range caps.Xcode.SDKs { sdkLower := strings.ToLower(sdk) if strings.Contains(sdkLower, "ios") { addLabel("ios") @@ -302,24 +303,24 @@ func generateSuggestedLabels(cap *RunnerCapabilities) []string { } } // If simulators available, add simulator label - if len(cap.Xcode.Simulators) > 0 { + if len(caps.Xcode.Simulators) > 0 { addLabel("ios-simulator") } } // Tool-based labels - if _, ok := cap.Tools["dotnet"]; ok { + if _, ok := caps.Tools["dotnet"]; ok { addLabel("dotnet") } - if _, ok := cap.Tools["java"]; ok { + if _, ok := caps.Tools["java"]; ok { addLabel("java") } - if _, ok := cap.Tools["node"]; ok { + if _, ok := caps.Tools["node"]; ok { addLabel("node") } // Build tool labels - for _, tool := range cap.BuildTools { + for _, tool := range caps.BuildTools { switch tool { case "msbuild": addLabel("msbuild") @@ -384,7 +385,7 @@ func detectDocker(ctx context.Context, dockerHost string) (bool, string) { if err != nil { return false, "" } - defer cli.Close() + defer func() { _ = cli.Close() }() timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() @@ -420,7 +421,7 @@ func detectDockerCompose(ctx context.Context) bool { return false } -func detectTools(ctx context.Context, cap *RunnerCapabilities) { +func detectTools(ctx context.Context, caps *RunnerCapabilities) { toolDetectors := map[string]func(context.Context) []string{ "node": detectNodeVersions, "go": detectGoVersions, @@ -439,7 +440,7 @@ func detectTools(ctx context.Context, cap *RunnerCapabilities) { for tool, detector := range toolDetectors { if versions := detector(ctx); len(versions) > 0 { - cap.Tools[tool] = versions + caps.Tools[tool] = versions } } @@ -460,23 +461,23 @@ func detectTools(ctx context.Context, cap *RunnerCapabilities) { for name, cmd := range simpleTools { if v := detectSimpleToolVersion(ctx, cmd); v != "" { - cap.Tools[name] = []string{v} + caps.Tools[name] = []string{v} } } } -func detectBuildTools(ctx context.Context, cap *RunnerCapabilities) { +func detectBuildTools(ctx context.Context, caps *RunnerCapabilities) { switch runtime.GOOS { case "windows": - detectWindowsBuildTools(ctx, cap) + detectWindowsBuildTools(ctx, caps) case "darwin": - detectMacOSBuildTools(ctx, cap) + detectMacOSBuildTools(caps) case "linux": - detectLinuxBuildTools(ctx, cap) + detectLinuxBuildTools(caps) } } -func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { +func detectWindowsBuildTools(ctx context.Context, caps *RunnerCapabilities) { // Check for Visual Studio via vswhere vswherePaths := []string{ `C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe`, @@ -486,7 +487,7 @@ func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { if _, err := os.Stat(vswhere); err == nil { cmd := exec.CommandContext(ctx, vswhere, "-latest", "-property", "displayName") if output, err := cmd.Output(); err == nil && len(output) > 0 { - cap.BuildTools = append(cap.BuildTools, "visual-studio") + caps.BuildTools = append(caps.BuildTools, "visual-studio") break } } @@ -503,7 +504,7 @@ func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { } for _, msbuild := range msbuildPaths { if _, err := os.Stat(msbuild); err == nil { - cap.BuildTools = append(cap.BuildTools, "msbuild") + caps.BuildTools = append(caps.BuildTools, "msbuild") break } } @@ -517,14 +518,14 @@ func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { } for _, iscc := range innoSetupPaths { if _, err := os.Stat(iscc); err == nil { - cap.BuildTools = append(cap.BuildTools, "inno-setup") + caps.BuildTools = append(caps.BuildTools, "inno-setup") break } } // Also check PATH if _, err := exec.LookPath("iscc"); err == nil { - if !contains(cap.BuildTools, "inno-setup") { - cap.BuildTools = append(cap.BuildTools, "inno-setup") + if !contains(caps.BuildTools, "inno-setup") { + caps.BuildTools = append(caps.BuildTools, "inno-setup") } } @@ -535,13 +536,13 @@ func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { } for _, nsis := range nsisPaths { if _, err := os.Stat(nsis); err == nil { - cap.BuildTools = append(cap.BuildTools, "nsis") + caps.BuildTools = append(caps.BuildTools, "nsis") break } } if _, err := exec.LookPath("makensis"); err == nil { - if !contains(cap.BuildTools, "nsis") { - cap.BuildTools = append(cap.BuildTools, "nsis") + if !contains(caps.BuildTools, "nsis") { + caps.BuildTools = append(caps.BuildTools, "nsis") } } @@ -552,7 +553,7 @@ func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { } for _, wix := range wixPaths { if _, err := os.Stat(wix); err == nil { - cap.BuildTools = append(cap.BuildTools, "wix") + caps.BuildTools = append(caps.BuildTools, "wix") break } } @@ -560,63 +561,63 @@ func detectWindowsBuildTools(ctx context.Context, cap *RunnerCapabilities) { // Check for signtool (Windows SDK) signtoolPaths, _ := filepath.Glob(`C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe`) if len(signtoolPaths) > 0 { - cap.BuildTools = append(cap.BuildTools, "signtool") + caps.BuildTools = append(caps.BuildTools, "signtool") } } -func detectMacOSBuildTools(ctx context.Context, cap *RunnerCapabilities) { +func detectMacOSBuildTools(caps *RunnerCapabilities) { // Check for xcpretty if _, err := exec.LookPath("xcpretty"); err == nil { - cap.BuildTools = append(cap.BuildTools, "xcpretty") + caps.BuildTools = append(caps.BuildTools, "xcpretty") } // Check for fastlane if _, err := exec.LookPath("fastlane"); err == nil { - cap.BuildTools = append(cap.BuildTools, "fastlane") + caps.BuildTools = append(caps.BuildTools, "fastlane") } // Check for CocoaPods if _, err := exec.LookPath("pod"); err == nil { - cap.BuildTools = append(cap.BuildTools, "cocoapods") + caps.BuildTools = append(caps.BuildTools, "cocoapods") } // Check for Carthage if _, err := exec.LookPath("carthage"); err == nil { - cap.BuildTools = append(cap.BuildTools, "carthage") + caps.BuildTools = append(caps.BuildTools, "carthage") } // Check for SwiftLint if _, err := exec.LookPath("swiftlint"); err == nil { - cap.BuildTools = append(cap.BuildTools, "swiftlint") + caps.BuildTools = append(caps.BuildTools, "swiftlint") } // Check for create-dmg or similar if _, err := exec.LookPath("create-dmg"); err == nil { - cap.BuildTools = append(cap.BuildTools, "create-dmg") + caps.BuildTools = append(caps.BuildTools, "create-dmg") } // Check for Packages (packagesbuild) if _, err := exec.LookPath("packagesbuild"); err == nil { - cap.BuildTools = append(cap.BuildTools, "packages") + caps.BuildTools = append(caps.BuildTools, "packages") } // Check for pkgbuild (built-in) if _, err := exec.LookPath("pkgbuild"); err == nil { - cap.BuildTools = append(cap.BuildTools, "pkgbuild") + caps.BuildTools = append(caps.BuildTools, "pkgbuild") } // Check for codesign (built-in) if _, err := exec.LookPath("codesign"); err == nil { - cap.BuildTools = append(cap.BuildTools, "codesign") + caps.BuildTools = append(caps.BuildTools, "codesign") } // Check for notarytool (built-in with Xcode) if _, err := exec.LookPath("notarytool"); err == nil { - cap.BuildTools = append(cap.BuildTools, "notarytool") + caps.BuildTools = append(caps.BuildTools, "notarytool") } } -func detectLinuxBuildTools(ctx context.Context, cap *RunnerCapabilities) { +func detectLinuxBuildTools(caps *RunnerCapabilities) { // Check for common Linux build tools tools := []string{ "gcc", "g++", "clang", "clang++", @@ -628,54 +629,54 @@ func detectLinuxBuildTools(ctx context.Context, cap *RunnerCapabilities) { for _, tool := range tools { if _, err := exec.LookPath(tool); err == nil { - cap.BuildTools = append(cap.BuildTools, tool) + caps.BuildTools = append(caps.BuildTools, tool) } } } -func detectPackageManagers(ctx context.Context, cap *RunnerCapabilities) { +func detectPackageManagers(_ context.Context, caps *RunnerCapabilities) { switch runtime.GOOS { case "windows": if _, err := exec.LookPath("choco"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "chocolatey") + caps.PackageManagers = append(caps.PackageManagers, "chocolatey") } if _, err := exec.LookPath("scoop"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "scoop") + caps.PackageManagers = append(caps.PackageManagers, "scoop") } if _, err := exec.LookPath("winget"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "winget") + caps.PackageManagers = append(caps.PackageManagers, "winget") } case "darwin": if _, err := exec.LookPath("brew"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "homebrew") + caps.PackageManagers = append(caps.PackageManagers, "homebrew") } if _, err := exec.LookPath("port"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "macports") + caps.PackageManagers = append(caps.PackageManagers, "macports") } case "linux": if _, err := exec.LookPath("apt"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "apt") + caps.PackageManagers = append(caps.PackageManagers, "apt") } if _, err := exec.LookPath("yum"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "yum") + caps.PackageManagers = append(caps.PackageManagers, "yum") } if _, err := exec.LookPath("dnf"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "dnf") + caps.PackageManagers = append(caps.PackageManagers, "dnf") } if _, err := exec.LookPath("pacman"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "pacman") + caps.PackageManagers = append(caps.PackageManagers, "pacman") } if _, err := exec.LookPath("zypper"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "zypper") + caps.PackageManagers = append(caps.PackageManagers, "zypper") } if _, err := exec.LookPath("apk"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "apk") + caps.PackageManagers = append(caps.PackageManagers, "apk") } if _, err := exec.LookPath("snap"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "snap") + caps.PackageManagers = append(caps.PackageManagers, "snap") } if _, err := exec.LookPath("flatpak"); err == nil { - cap.PackageManagers = append(cap.PackageManagers, "flatpak") + caps.PackageManagers = append(caps.PackageManagers, "flatpak") } } } @@ -813,13 +814,8 @@ func detectPwshVersion(ctx context.Context, cmd string) string { timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() - // Use -Command to get version - var c *exec.Cmd - if cmd == "pwsh" { - c = exec.CommandContext(timeoutCtx, cmd, "-Command", "$PSVersionTable.PSVersion.ToString()") - } else { - c = exec.CommandContext(timeoutCtx, cmd, "-Command", "$PSVersionTable.PSVersion.ToString()") - } + // Use -Command to get version (same command works for both pwsh and powershell) + c := exec.CommandContext(timeoutCtx, cmd, "-Command", "$PSVersionTable.PSVersion.ToString()") output, err := c.Output() if err != nil { @@ -1042,15 +1038,9 @@ func getContainerCPUUsage() float64 { } } - // Try reading /proc/stat for this process's CPU usage - if data, err := os.ReadFile("/proc/self/stat"); err == nil { - fields := strings.Fields(string(data)) - if len(fields) >= 15 { - // Fields 14 and 15 are utime and stime (in clock ticks) - // This is cumulative, not instantaneous - // For containers, we'll report 0 rather than misleading host data - } - } + // Note: Reading /proc/self/stat could give us utime and stime (fields 14 and 15), + // but these are cumulative values, not instantaneous. For containers, we report 0 + // rather than misleading host data. return -1 // Unable to determine - caller should handle } diff --git a/internal/pkg/envcheck/docker.go b/internal/pkg/envcheck/docker.go index 65aae4d..1e1e80e 100644 --- a/internal/pkg/envcheck/docker.go +++ b/internal/pkg/envcheck/docker.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/client" ) +// CheckIfDockerRunning verifies that the Docker daemon is running and accessible. func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error { opts := []client.Opt{ client.FromEnv, @@ -23,7 +24,7 @@ func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error { if err != nil { return err } - defer cli.Close() + defer func() { _ = cli.Close() }() _, err = cli.Ping(ctx) if err != nil { diff --git a/internal/pkg/labels/labels.go b/internal/pkg/labels/labels.go index 542b52d..974bad0 100644 --- a/internal/pkg/labels/labels.go +++ b/internal/pkg/labels/labels.go @@ -1,6 +1,7 @@ // Copyright 2023 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// Package labels provides utilities for parsing and managing runner labels. package labels import ( @@ -8,17 +9,20 @@ import ( "strings" ) +// Label scheme constants define the execution environments. const ( SchemeHost = "host" SchemeDocker = "docker" ) +// Label represents a parsed runner label with name, schema, and optional argument. type Label struct { Name string Schema string Arg string } +// Parse parses a label string in the format "name:schema:arg" and returns a Label. func Parse(str string) (*Label, error) { splits := strings.SplitN(str, ":", 3) label := &Label{ @@ -38,8 +42,10 @@ func Parse(str string) (*Label, error) { return label, nil } +// Labels is a slice of Label pointers. type Labels []*Label +// RequireDocker returns true if any label uses the docker schema. func (l Labels) RequireDocker() bool { for _, label := range l { if label.Schema == SchemeDocker { @@ -49,6 +55,7 @@ func (l Labels) RequireDocker() bool { return false } +// PickPlatform selects the appropriate platform based on the runsOn requirements. func (l Labels) PickPlatform(runsOn []string) string { platforms := make(map[string]string, len(l)) for _, label := range l { @@ -82,6 +89,7 @@ func (l Labels) PickPlatform(runsOn []string) string { return "docker.gitea.com/runner-images:ubuntu-latest" } +// Names returns the names of all labels. func (l Labels) Names() []string { names := make([]string, 0, len(l)) for _, label := range l { @@ -90,6 +98,7 @@ func (l Labels) Names() []string { return names } +// ToStrings converts labels back to their string representation. func (l Labels) ToStrings() []string { ls := make([]string, 0, len(l)) for _, label := range l { diff --git a/internal/pkg/report/reporter.go b/internal/pkg/report/reporter.go index b88773a..50c9044 100644 --- a/internal/pkg/report/reporter.go +++ b/internal/pkg/report/reporter.go @@ -1,6 +1,7 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// Package report provides task reporting functionality for communicating with the server. package report import ( @@ -21,6 +22,7 @@ import ( "git.marketally.com/gitcaddy/gitcaddy-runner/internal/pkg/client" ) +// Reporter handles logging and state reporting for running tasks. type Reporter struct { ctx context.Context cancel context.CancelFunc @@ -42,6 +44,7 @@ type Reporter struct { stopCommandEndToken string } +// NewReporter creates a new Reporter for the given task. func NewReporter(ctx context.Context, cancel context.CancelFunc, client client.Client, task *runnerv1.Task) *Reporter { var oldnew []string if v := task.Context.Fields["token"].GetStringValue(); v != "" { @@ -72,6 +75,7 @@ func NewReporter(ctx context.Context, cancel context.CancelFunc, client client.C return rv } +// ResetSteps initializes the step states with the given number of steps. func (r *Reporter) ResetSteps(l int) { r.stateMu.Lock() defer r.stateMu.Unlock() @@ -82,6 +86,7 @@ func (r *Reporter) ResetSteps(l int) { } } +// Levels returns all log levels that this hook should fire for. func (r *Reporter) Levels() []log.Level { return log.AllLevels } @@ -93,6 +98,7 @@ func appendIfNotNil[T any](s []*T, v *T) []*T { return s } +// Fire processes a log entry and updates the task state accordingly. func (r *Reporter) Fire(entry *log.Entry) error { r.stateMu.Lock() defer r.stateMu.Unlock() @@ -175,6 +181,7 @@ func (r *Reporter) Fire(entry *log.Entry) error { return nil } +// RunDaemon starts the periodic reporting of logs and state. func (r *Reporter) RunDaemon() { if r.closed { return @@ -189,6 +196,7 @@ func (r *Reporter) RunDaemon() { time.AfterFunc(time.Second, r.RunDaemon) } +// Logf adds a formatted log message to the report. func (r *Reporter) Logf(format string, a ...interface{}) { r.stateMu.Lock() defer r.stateMu.Unlock() @@ -205,6 +213,7 @@ func (r *Reporter) logf(format string, a ...interface{}) { } } +// SetOutputs stores the job outputs to be reported to the server. func (r *Reporter) SetOutputs(outputs map[string]string) { r.stateMu.Lock() defer r.stateMu.Unlock() @@ -225,6 +234,7 @@ func (r *Reporter) SetOutputs(outputs map[string]string) { } } +// Close finalizes the report and sends any remaining logs and state. func (r *Reporter) Close(lastWords string) error { r.closed = true @@ -260,6 +270,7 @@ func (r *Reporter) Close(lastWords string) error { }, retry.Context(r.ctx)) } +// ReportLog sends accumulated log rows to the server. func (r *Reporter) ReportLog(noMore bool) error { r.clientM.Lock() defer r.clientM.Unlock() @@ -295,6 +306,7 @@ func (r *Reporter) ReportLog(noMore bool) error { return nil } +// ReportState sends the current task state to the server. func (r *Reporter) ReportState() error { r.clientM.Lock() defer r.clientM.Unlock() @@ -373,7 +385,7 @@ func (r *Reporter) parseResult(result interface{}) (runnerv1.Result, bool) { var cmdRegex = regexp.MustCompile(`^::([^ :]+)( .*)?::(.*)$`) -func (r *Reporter) handleCommand(originalContent, command, parameters, value string) *string { +func (r *Reporter) handleCommand(originalContent, command, _ /* parameters */, value string) *string { if r.stopCommandEndToken != "" && command != r.stopCommandEndToken { return &originalContent } diff --git a/internal/pkg/ver/version.go b/internal/pkg/ver/version.go index 58d195c..31ebcac 100644 --- a/internal/pkg/ver/version.go +++ b/internal/pkg/ver/version.go @@ -1,11 +1,13 @@ // Copyright 2023 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// Package ver provides version information for the runner. package ver // go build -ldflags "-X git.marketally.com/gitcaddy/gitcaddy-runner/internal/pkg/ver.version=1.2.3" var version = "dev" +// Version returns the current runner version. func Version() string { return version } diff --git a/main.go b/main.go index 0ec436b..6f37f8e 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT +// GitCaddy Runner is a CI/CD runner for Gitea Actions. package main import (