diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f087f378a..e29f83c93 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - go_version: ['1.24'] + go_version: ['1.25'] os: [ubuntu-latest, windows-latest, macos-latest] env: OS: ${{ matrix.os }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9bba41c85..2573e4994 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -53,7 +53,7 @@ jobs: - name: Set up Go (latest version) uses: actions/setup-go@v5 with: - go-version: '>=1.24.0' + go-version: '>=1.25.0' check-latest: true # Initializes the CodeQL tools for scanning. diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index a4227b496..8c40d8bd6 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -26,7 +26,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: ~1.24 + go-version: ~1.25 - name: Check configuration snippets in documentation run: go run ./config/checkdoc -r docs/content -i changelog.md diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6b550e311..cbf21efbc 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -24,7 +24,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: ~1.24 + go-version: ~1.25 check-latest: true - name: Set up QEMU diff --git a/.github/workflows/release-doc.yml b/.github/workflows/release-doc.yml index e79efbd07..7e2b044a9 100644 --- a/.github/workflows/release-doc.yml +++ b/.github/workflows/release-doc.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: ~1.24 + go-version: ~1.25 - name: Check configuration snippets in documentation run: go run ./config/checkdoc -r docs/content -i changelog.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 280c5f626..287ff322e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: ~1.24 + go-version: ~1.25 check-latest: true - name: Set up QEMU diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 2a8cb7ff9..4ab36e6a9 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: ~1.24 + go-version: ~1.25 check-latest: true - name: Set up QEMU diff --git a/.golangci.yml b/.golangci.yml index c82587b24..96ee5c20b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,7 +22,7 @@ linters: - gocheckcompilerdirectives - gochecksumtype # - gocritic - # - godoclint + - godoclint - goheader - gomoddirectives - gosec diff --git a/commands_display.go b/commands_display.go index 15d13f0e2..5737cdf76 100644 --- a/commands_display.go +++ b/commands_display.go @@ -398,7 +398,7 @@ func (l *lineLengthWriter) Write(p []byte) (n int, err error) { n += written + 1 _, _ = l.writer.Write(l.tokens[1:]) // write break (instead of WS at lastWhiteIndex) - for j := 0; j < l.breakLength; j++ { + for range l.breakLength { _, _ = l.writer.Write(l.tokens[0:1]) // fill spaces for alignment } diff --git a/darwin/calendar_interval.go b/darwin/calendar_interval.go index 7c9b525fa..2154c29b3 100644 --- a/darwin/calendar_interval.go +++ b/darwin/calendar_interval.go @@ -36,7 +36,7 @@ func (c *CalendarInterval) clone() *CalendarInterval { return clone } -// getCalendarIntervalsFromSchedules converts schedules into launchd calendar events +// GetCalendarIntervalsFromSchedules converts schedules into launchd calendar events // let's say we've setup these rules: // // Mon-Fri *-*-* *:0,30:00 = every half hour @@ -114,7 +114,7 @@ func setCalendarIntervalValueFromType(entry *CalendarInterval, value int, typeVa } } -// parseCalendarIntervals converts calendar intervals into a single calendar event. +// ParseCalendarIntervals converts calendar intervals into a single calendar event. // TODO: find a pattern on how to split into multiple events when needed func ParseCalendarIntervals(intervals []CalendarInterval) []string { event := calendar.NewEvent(func(e *calendar.Event) { diff --git a/flags.go b/flags.go index 174ce88f9..595009676 100644 --- a/flags.go +++ b/flags.go @@ -58,7 +58,7 @@ func envValueOverride[T any](defaultValue T, keys ...string) T { v = value } if err == nil { - defaultValue = v.(T) + defaultValue = v.(T) //nolint:forcetypeassert } else { clog.Errorf("cannot convert env variable %s=%q: %s", key, value, err.Error()) } diff --git a/go.mod b/go.mod index 4822f512f..007fc578c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/creativeprojects/resticprofile -go 1.24.7 +go 1.25.1 require ( github.com/Masterminds/semver/v3 v3.4.0 diff --git a/lock/lock_test.go b/lock/lock_test.go index 43ada7c49..094bc9ca7 100644 --- a/lock/lock_test.go +++ b/lock/lock_test.go @@ -268,53 +268,57 @@ func TestLockWithNoInterruption(t *testing.T) { } func TestLockIsRemovedAfterInterruptSignal(t *testing.T) { - t.Parallel() - if platform.IsWindows() { t.Skip("cannot send a signal to a child process in Windows") } + t.Parallel() lockfile := getTempfile(t) var err error buffer := &bytes.Buffer{} - cmd := exec.Command(helperBinary, "-wait", "2000", "-lock", lockfile) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + cmd := exec.CommandContext(ctx, helperBinary, "-wait", "2000", "-lock", lockfile) cmd.Stdout = buffer cmd.Stderr = buffer err = cmd.Start() - require.NoError(t, err) + require.NoError(t, err, "starting child process") time.Sleep(300 * time.Millisecond) err = cmd.Process.Signal(syscall.SIGINT) - require.NoError(t, err) + require.NoError(t, err, "sending interrupt signal to child process") err = cmd.Wait() - assert.NoError(t, err) + assert.NoError(t, err, "waiting for child process to finish") assert.Equal(t, "lock acquired\ntask interrupted\nlock released\n", buffer.String()) } func TestLockIsRemovedAfterInterruptSignalInsideShell(t *testing.T) { - t.Parallel() - if platform.IsWindows() { t.Skip("cannot send a signal to a child process in Windows") } + t.Parallel() lockfile := getTempfile(t) var err error buffer := &bytes.Buffer{} - cmd := exec.Command("sh", "-c", "exec "+helperBinary+" -wait 2000 -lock "+lockfile) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + cmd := exec.CommandContext(ctx, "sh", "-c", "exec "+helperBinary+" -wait 2000 -lock "+lockfile) cmd.Stdout = buffer cmd.Stderr = buffer err = cmd.Start() - require.NoError(t, err) + require.NoError(t, err, "starting child process inside a shell") time.Sleep(300 * time.Millisecond) err = cmd.Process.Signal(syscall.SIGINT) - require.NoError(t, err) + require.NoError(t, err, "sending interrupt signal to child process") err = cmd.Wait() - assert.NoError(t, err) + assert.NoError(t, err, "waiting for child process to finish") assert.Equal(t, "lock acquired\ntask interrupted\nlock released\n", buffer.String()) } diff --git a/lock/test/main.go b/lock/test/main.go index 6e6cfd4e0..63fce4683 100644 --- a/lock/test/main.go +++ b/lock/test/main.go @@ -20,6 +20,12 @@ func main() { flag.StringVar(&lockfile, "lock", "test.lock", "Name of the lock file") flag.Parse() + // Catch CTR-C key + sigChan := make(chan os.Signal, 2) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGABRT) + // remove signal catch before leaving + defer signal.Stop(sigChan) + l := lock.NewLock(lockfile) if l.TryAcquire() { defer func() { @@ -27,12 +33,6 @@ func main() { fmt.Println("lock released") }() - // Catch CTR-C key - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGABRT) - // remove signal catch before leaving - defer signal.Stop(sigChan) - fmt.Println("lock acquired") select { diff --git a/mask/mask.go b/mask/mask.go index a1fb7f799..fc9164e51 100644 --- a/mask/mask.go +++ b/mask/mask.go @@ -5,8 +5,8 @@ import "regexp" const maskReplacement = "×××" var ( - // httpHeaderNames = regexp.MustCompile("(?i)^(Authorization)$") RepositoryConfidentialPart = regexp.MustCompile("[:/][^:/@]+?:([^:@]+?)@[^:/@]+?") // user:pass@host + // httpHeaderNames = regexp.MustCompile("(?i)^(Authorization)$") // urlEnvKeys = regexp.MustCompile("(?i)^.+(_AUTH|_URL)$") // hiddenEnvKeys = regexp.MustCompile("(?i)^(.+_KEY|.+_TOKEN|.*PASSWORD.*|.*SECRET.*)$") ) diff --git a/schedule/config.go b/schedule/config.go index 6c56276c7..804b1fcb0 100644 --- a/schedule/config.go +++ b/schedule/config.go @@ -45,7 +45,7 @@ func (s *Config) SetCommand(wd, command string, args []string) { s.Arguments = NewCommandArguments(args) } -// Priority is either "background" or "standard" +// GetPriority is either "background" or "standard" func (s *Config) GetPriority() string { s.Priority = strings.ToLower(s.Priority) // default value for priority is "standard" diff --git a/schedule/handler_systemd.go b/schedule/handler_systemd.go index 0c352e1e0..d8698ea7c 100644 --- a/schedule/handler_systemd.go +++ b/schedule/handler_systemd.go @@ -93,6 +93,7 @@ func (h *HandlerSystemd) DisplaySchedules(profile, command string, schedules []s return displaySystemdSchedules(profile, command, schedules) } +// DisplayStatus displays the status of all the timers installed on that profile. Example: // Timers summary // =============== // NEXT LEFT LAST PASSED UNIT ACTIVATES @@ -318,7 +319,7 @@ func (h *HandlerSystemd) Scheduled(profileName string) ([]Config, error) { return configs, nil } -// detectSchedulePermission returns the permission defined from the configuration, +// DetectSchedulePermission returns the permission defined from the configuration, // or the best guess considering the current user permission. // safe specifies whether a guess may lead to a too broad or too narrow file access permission. func (h *HandlerSystemd) DetectSchedulePermission(p Permission) (Permission, bool) { diff --git a/schedule/handler_windows.go b/schedule/handler_windows.go index 363fdf271..6f385a831 100644 --- a/schedule/handler_windows.go +++ b/schedule/handler_windows.go @@ -104,7 +104,7 @@ func (h *HandlerWindows) RemoveJob(job *Config, _ Permission) error { return nil } -// DisplayStatus display some information about the task scheduler job +// DisplayJobStatus display some information about the task scheduler job func (h *HandlerWindows) DisplayJobStatus(job *Config) error { err := schtasks.Status(job.ProfileName, job.CommandName) if err != nil { @@ -139,7 +139,7 @@ func (h *HandlerWindows) Scheduled(profileName string) ([]Config, error) { return configs, nil } -// detectSchedulePermission returns the permission defined from the configuration, +// DetectSchedulePermission returns the permission defined from the configuration, // or the best guess considering the current user permission. // safe specifies whether a guess may lead to a too broad or too narrow file access permission. func (h *HandlerWindows) DetectSchedulePermission(permission Permission) (Permission, bool) { diff --git a/schtasks/principal.go b/schtasks/principal.go index 9458a2249..7dee8fdfa 100644 --- a/schtasks/principal.go +++ b/schtasks/principal.go @@ -15,7 +15,7 @@ type Principal struct { RunLevel RunLevel `xml:"RunLevel,omitempty"` } -// LongType specifies the security logon method required to run those tasks associated with the principal. +// LogonType specifies the security logon method required to run those tasks associated with the principal. // https://learn.microsoft.com/en-us/windows/win32/taskschd/taskschedulerschema-logontype-principaltype-element type LogonType string @@ -25,7 +25,7 @@ const ( LogonTypeInteractiveToken LogonType = "InteractiveToken" // User must already be logged on. The task will be run only in an existing interactive session. ) -// The identifier that is used to specify the privilege level that is required to run the tasks that are associated with the principal. +// RunLevel is the identifier that is used to specify the privilege level that is required to run the tasks that are associated with the principal. // https://learn.microsoft.com/en-us/windows/win32/taskschd/taskschedulerschema-runleveltype-simpletype type RunLevel string diff --git a/schtasks/settings.go b/schtasks/settings.go index b9e4036e8..3392cec89 100644 --- a/schtasks/settings.go +++ b/schtasks/settings.go @@ -34,7 +34,7 @@ type IdleSettings struct { WaitTimeout period.Period `xml:"WaitTimeout"` // the amount of time that the Task Scheduler will wait for an idle condition to occur } -// For scripting, gets or sets an integer value that indicates which version of Task Scheduler a task is compatible with. +// Compatibility is an integer value that indicates which version of Task Scheduler a task is compatible with. type Compatibility int const ( diff --git a/schtasks/taskscheduler.go b/schtasks/taskscheduler.go index e728d0a29..7587dbc92 100644 --- a/schtasks/taskscheduler.go +++ b/schtasks/taskscheduler.go @@ -1,5 +1,7 @@ //go:build windows +// Package schtasks +// // Schedule types on Windows: // ========================== // 1. one time: diff --git a/shell/arg.go b/shell/arg.go index 0099edee1..2bf523577 100644 --- a/shell/arg.go +++ b/shell/arg.go @@ -71,7 +71,7 @@ func (a Arg) Clone() Arg { } } -// IsEmpty means the flag is specifically empty, not just a flag without a value +// IsEmptyValue means the flag is specifically empty, not just a flag without a value // (e.g. --flag="") func (a Arg) IsEmptyValue() bool { return a.empty @@ -84,7 +84,7 @@ func (a Arg) HasValue() bool { return a.empty || a.value != "" } -// IsConfidential returns true if the argument may contain credentials. +// HasConfidentialFilter returns true if the argument may contain credentials. func (a Arg) HasConfidentialFilter() bool { return a.confidentialFilter != nil } diff --git a/term/term.go b/term/term.go index b6e54d54f..0f288592f 100644 --- a/term/term.go +++ b/term/term.go @@ -86,7 +86,7 @@ func OsStdoutIsTerminal() bool { return term.IsTerminal(fd) } -// OsStdoutIsTerminal returns true as os.Stdout is a terminal session +// OsStdoutTerminalSize returns true as os.Stdout is a terminal session func OsStdoutTerminalSize() (width, height int) { fd := fdToInt(os.Stdout.Fd()) var err error