Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @alexander-kolodka
42 changes: 42 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: CI
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: stable
- run: go install github.com/ctrf-io/go-ctrf-json-reporter/cmd/go-ctrf-json-reporter@latest
- run: go test -json ./... | go-ctrf-json-reporter -output ctrf-report.json
- uses: ctrf-io/github-test-reporter@v1
with:
report-path: 'ctrf-report.json'

summary-report: true
annotate: true
failed-report: true
slowest-report: true

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: always()

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: stable
- uses: golangci/golangci-lint-action@v9
with:
version: v2.6
17 changes: 17 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ formatters:
# Default: 100
max-len: 120

gci:
# Section configuration to compare against.
# Section names are case-insensitive and may contain parameters in ().
# The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`.
# If `custom-order` is `true`, it follows the order of `sections` option.
# Default: ["standard", "default"]
sections:
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
- localmodule # Local module section: contains all local packages. This section is not present unless explicitly enabled.
# Checks that no inline comments are present.
# Default: false
no-inline-comments: true
# Checks that no prefix comments (comment lines above an import) are present.
# Default: false
no-prefix-comments: true

linters:
enable:
- asasalint # checks for pass []any as any in variadic func(...any)
Expand Down
7 changes: 5 additions & 2 deletions cmd/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package cmd
import (
"errors"

"github.com/samber/lo"
"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/backup"
"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/alexander-kolodka/crestic/internal/healthchecks"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/samber/lo"
"github.com/spf13/cobra"
)

var backupCmd = &cobra.Command{
Expand Down Expand Up @@ -81,6 +82,8 @@ func init() {
backupCmd.Flags().BoolP("all", "a", false, "Check all repositories")
backupCmd.Flags().StringSliceP("job", "j", nil, "Run only specific jobs by name (comma-separated)")
backupCmd.Flags().Bool("dry-run", false, "Dry run")

_ = backupCmd.RegisterFlagCompletionFunc("job", jobAutocompletion)
}

func filterJobs(cmd *cobra.Command, backups []entity.Job) []entity.Job {
Expand Down
3 changes: 2 additions & 1 deletion cmd/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"os"
"path/filepath"

"gopkg.in/yaml.v3"

"github.com/alexander-kolodka/crestic/internal/dto"
"github.com/alexander-kolodka/crestic/internal/entity"
"gopkg.in/yaml.v3"
)

// findConfigFile searches for config file in priority order:
Expand Down
3 changes: 2 additions & 1 deletion cmd/check.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/check"
"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/spf13/cobra"
)

var checkCmd = &cobra.Command{
Expand Down
3 changes: 2 additions & 1 deletion cmd/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"path/filepath"
"strings"

"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/backup"
"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/cron"
"github.com/alexander-kolodka/crestic/internal/healthchecks"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/spf13/cobra"
)

var cronCmd = &cobra.Command{
Expand Down
5 changes: 4 additions & 1 deletion cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package cmd
import (
"errors"

"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/exec"
"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/spf13/cobra"
)

var execCmd = &cobra.Command{
Expand Down Expand Up @@ -96,4 +97,6 @@ func init() {
execCmd.Flags().
StringSliceP("repo", "r", nil, "Repository/repositories to execute command on (can specify multiple)")
execCmd.Flags().BoolP("all", "a", false, "Execute on all repositories")

_ = execCmd.RegisterFlagCompletionFunc("repo", repoAutocompletion)
}
5 changes: 4 additions & 1 deletion cmd/forget.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/forget"
"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/spf13/cobra"
)

var forgetCmd = &cobra.Command{
Expand Down Expand Up @@ -77,4 +78,6 @@ func init() {
forgetCmd.Flags().BoolP("all", "a", false, "Run forget for all jobs")
forgetCmd.Flags().Bool("dry-run", false, "Show what would be deleted without actually deleting")
forgetCmd.Flags().Bool("prune", false, "Actually remove the data (frees up space)")

_ = forgetCmd.RegisterFlagCompletionFunc("repo", repoAutocompletion)
}
26 changes: 25 additions & 1 deletion cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"errors"
"fmt"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/rs/zerolog"
"github.com/samber/lo"
"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/entity"
)

// getRepos returns the list of repositories to operate on based on command flags.
Expand Down Expand Up @@ -58,3 +59,26 @@ func toZerologLevel(level string) zerolog.Level {

return levels[level]
}

func jobAutocompletion(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
cfgPath, _ := cmd.Flags().GetString("config")
cfg, err := loadConfig(cfgPath)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}

jobNames := lo.Map(cfg.Jobs, func(j entity.Job, _ int) string {
return j.GetName()
})

return jobNames, cobra.ShellCompDirectiveNoFileComp
}

func repoAutocompletion(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
cfgPath, _ := cmd.Flags().GetString("config")
cfg, err := loadConfig(cfgPath)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
return lo.Keys(cfg.Repositories), cobra.ShellCompDirectiveNoFileComp
}
6 changes: 4 additions & 2 deletions cmd/restore.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/cases/restore"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/spf13/cobra"
)

var restoreCmd = &cobra.Command{
Expand Down Expand Up @@ -64,6 +65,7 @@ func init() {
restoreCmd.Flags().StringP("repo", "r", "", "Restore specific repository (required)")
restoreCmd.Flags().StringP("target", "t", "", "Directory to restore to (required)")
restoreCmd.Flags().StringP("snapshot", "s", "", "snapshot")
_ = restoreCmd.MarkFlagRequired("to")
_ = restoreCmd.MarkFlagRequired("target")

_ = restoreCmd.RegisterFlagCompletionFunc("repo", repoAutocompletion)
}
12 changes: 11 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"context"
"errors"

"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/logger"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/alexander-kolodka/crestic/internal/version"
"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
Expand Down Expand Up @@ -68,6 +69,15 @@ func init() {
rootCmd.PersistentFlags().Bool("print-commands", false, "Print executed shell commands")

rootCmd.SilenceUsage = true

_ = rootCmd.MarkFlagFilename("config", "yaml", "yml")

_ = rootCmd.RegisterFlagCompletionFunc(
"log-level",
func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"debug", "info", "warn", "error"}, cobra.ShellCompDirectiveDefault
},
)
}

func logFormat(ci, json bool) logger.Format {
Expand Down
5 changes: 4 additions & 1 deletion cmd/unlock.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/cases/unlock"
"github.com/alexander-kolodka/crestic/internal/restic"
"github.com/alexander-kolodka/crestic/internal/shell"
"github.com/spf13/cobra"
)

var unlockCmd = &cobra.Command{
Expand Down Expand Up @@ -63,4 +64,6 @@ func init() {
rootCmd.AddCommand(unlockCmd)
unlockCmd.Flags().StringSliceP("repo", "r", nil, "Unlock specific repository/repositories (can specify multiple)")
unlockCmd.Flags().BoolP("all", "a", false, "Unlock all repositories")

_ = unlockCmd.RegisterFlagCompletionFunc("repo", repoAutocompletion)
}
3 changes: 2 additions & 1 deletion internal/cases/backup/healthcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package backup
import (
"context"

"github.com/google/uuid"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/alexander-kolodka/crestic/internal/healthchecks"
"github.com/google/uuid"
)

// newHealthcheckMw wraps a do func with Healthchecks.io monitoring.
Expand Down
3 changes: 2 additions & 1 deletion internal/cases/backup/mw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"context"
"testing"

"github.com/stretchr/testify/require"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/alexander-kolodka/crestic/internal/testutils"
"github.com/stretchr/testify/require"
)

func TestChain(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion internal/cases/handler/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"context"
"testing"

"github.com/stretchr/testify/require"

"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/testutils"
"github.com/stretchr/testify/require"
)

func TestChain(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion internal/cases/handler/lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (
"path/filepath"
"sync"

"github.com/alexander-kolodka/crestic/internal/logger"
"github.com/gofrs/flock"

"github.com/alexander-kolodka/crestic/internal/logger"
)

// WithLock wraps a handler with file-based locking to prevent concurrent execution.
Expand Down
5 changes: 3 additions & 2 deletions internal/cases/handler/panic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
"errors"
"testing"

"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/panix"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/alexander-kolodka/crestic/internal/cases/handler"
"github.com/alexander-kolodka/crestic/internal/panix"
)

func TestWithPanicRecoveryCatchesPanic(t *testing.T) {
Expand Down
5 changes: 3 additions & 2 deletions internal/cron/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"context"
"time"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/alexander-kolodka/crestic/internal/logger"
"github.com/robfig/cron/v3"
"github.com/samber/lo"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/alexander-kolodka/crestic/internal/logger"
)

// FilterJobsByCron filters jobs that should run based on their cron expressions.
Expand Down
3 changes: 2 additions & 1 deletion internal/dto/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"fmt"
"strings"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/samber/lo"

"github.com/alexander-kolodka/crestic/internal/entity"
)

func ToEntity(cfg Config) (*entity.Config, error) {
Expand Down
3 changes: 2 additions & 1 deletion internal/entity/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import (
"sort"
"testing"

"github.com/alexander-kolodka/crestic/internal/entity"
"github.com/google/go-cmp/cmp"

"github.com/alexander-kolodka/crestic/internal/entity"
)

func TestOptions_ToArgs(t *testing.T) {
Expand Down
Loading