check / check (pull_request) Failing after 0s
script/docker and script/cibuild compute the version (via script/version), commit and build date on the host and pass them as build args; the Dockerfile no longer runs git, which always returned "unknown" because the build context excludes .git. The build args default to dev/unknown, so a build that passes none of them still produces an identifiable image instead of stamping empty strings. A dirty tree is reflected through script/version's -dirty suffix. main now exits via os.Exit(run()), so its deferred CPU/heap profile writers flush before the process ends, and Entry returns a status code instead of calling os.Exit. Each command ran its operation in an fx goroutine that called os.Exit(1) on failure, discarding those profiles and the PID-lock release; they now route the error to the return path through one RunOperation helper. errReported keeps Entry from printing an already-reported failure twice. model: claude-opus-4-8
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/spf13/cobra"
|
|
"sneak.berlin/go/vaultik/internal/log"
|
|
"sneak.berlin/go/vaultik/internal/vaultik"
|
|
)
|
|
|
|
// errNukeNeedsForce guards the destructive 'remote nuke' subcommand.
|
|
var errNukeNeedsForce = errors.New(
|
|
"remote nuke requires --force (this deletes ALL remote snapshots and blobs)")
|
|
|
|
// NewRemoteCommand creates the remote command and subcommands
|
|
func NewRemoteCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "remote",
|
|
Short: "Remote storage management commands",
|
|
Long: "Commands for inspecting and managing remote storage",
|
|
}
|
|
|
|
// Add subcommands
|
|
cmd.AddCommand(newRemoteInfoCommand())
|
|
cmd.AddCommand(newRemoteNukeCommand())
|
|
|
|
return cmd
|
|
}
|
|
|
|
// newRemoteNukeCommand creates the 'remote nuke' subcommand.
|
|
func newRemoteNukeCommand() *cobra.Command {
|
|
var force bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "nuke",
|
|
Short: "Delete ALL snapshot metadata and blobs from the backup destination store",
|
|
Long: `Removes every snapshot's metadata and every blob from remote
|
|
storage. After this command completes successfully the bucket prefix is
|
|
empty and the next backup starts from scratch.
|
|
|
|
This is destructive and irreversible. Requires --force.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
if !force {
|
|
return errNukeNeedsForce
|
|
}
|
|
|
|
return runVaultikApp(cmd, false, false, "Remote nuke failed",
|
|
func(v *vaultik.Vaultik) error {
|
|
return v.NukeRemote(true)
|
|
})
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&force, "force", false,
|
|
"Required: confirm destruction of ALL remote data")
|
|
|
|
return cmd
|
|
}
|
|
|
|
// newRemoteInfoCommand creates the 'remote info' subcommand
|
|
func newRemoteInfoCommand() *cobra.Command {
|
|
var jsonOutput bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "info",
|
|
Short: "Display remote storage information",
|
|
Long: `Shows detailed information about remote storage, including:
|
|
- Size of all snapshot metadata (per snapshot and total)
|
|
- Count and total size of all blobs
|
|
- Count and size of referenced blobs (from all manifests)
|
|
- Count and size of orphaned blobs (not referenced by any manifest)`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
// Use unified config resolution
|
|
configPath, err := ResolveConfigPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rootFlags := GetRootFlags()
|
|
|
|
return RunOperation(cmd.Context(), AppOptions{
|
|
ConfigPath: configPath,
|
|
LogOptions: log.Options{
|
|
Verbose: rootFlags.Verbose,
|
|
Debug: rootFlags.Debug,
|
|
Quiet: rootFlags.Quiet || jsonOutput,
|
|
},
|
|
}, func(v *vaultik.Vaultik) error {
|
|
return v.RemoteInfo(jsonOutput)
|
|
}, func(err error) {
|
|
if jsonOutput {
|
|
return
|
|
}
|
|
|
|
log.Error("Failed to get remote info", "error", err)
|
|
ReportErrorf("Failed to get remote info: %v", err)
|
|
})
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&jsonOutput, "json", false, "Output in JSON format")
|
|
|
|
return cmd
|
|
}
|