feat: backup profiles (RFC 0010)#86
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
c3d648e to
1425ca1
Compare
1425ca1 to
1ce7258
Compare
There was a problem hiding this comment.
Pull request overview
This PR implements RFC 0010 “backup profiles”: a YAML-driven configuration model for reusable stores/auth entries and named backup presets, with new CLI surfaces to manage them and profile-aware backup execution.
Changes:
- Add
ProfilesConfigYAML model + load/save APIs ininternal/engine, exported viaclient.go. - Add new CLI commands:
cloudstic {profile,auth,store} {list,show,new}plusauth login. - Extend
cloudstic backupwith-profile,-all-profiles,-auth-ref,-profiles-file, and profile-based merge/precedence behavior.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
rfcs/README.md |
Index RFC 0010 in the RFC catalog. |
rfcs/0010-backup-profiles.md |
Add RFC detailing YAML schema, precedence rules, and CLI UX. |
internal/engine/profiles.go |
Define YAML schema structs and implement load/save with normalization + atomic write. |
internal/engine/profiles_test.go |
Add tests for config normalization and save/load round-trip. |
client.go |
Re-export profile types and expose LoadProfilesFile / SaveProfilesFile on the public API. |
pkg/store/s3.go |
Add S3 shared-config profile support via WithS3Profile + config.WithSharedConfigProfile. |
pkg/source/gdrive.go |
Ensure token directory exists before writing Google token file. |
pkg/source/onedrive.go |
Ensure token directory exists before writing OneDrive token file. |
cmd/cloudstic/main.go |
Wire new top-level commands: profile, auth, store. |
cmd/cloudstic/runner.go |
Add --no-prompt handling and early global-flag detection helper. |
cmd/cloudstic/interactive.go |
Add shared interactive prompt helpers gated by --no-prompt. |
cmd/cloudstic/flags.go |
Add global -profile, -profiles-file, -s3-profile and helper for detecting provided flags. |
cmd/cloudstic/store.go |
Apply profile-based store overrides before opening store/client; gate prompts on --no-prompt; pass WithS3Profile. |
cmd/cloudstic/cmd_backup.go |
Implement profile-aware backup execution, -all-profiles sequencing, auth-ref application, and default auth persistence. |
cmd/cloudstic/cmd_backup_profile_test.go |
Add tests for profile/store/auth merge and precedence behavior in backup. |
cmd/cloudstic/cmd_store.go |
Implement store list/show/new, including optional interactive encryption/setup. |
cmd/cloudstic/cmd_store_test.go |
Add store command tests including encryption fields, validation, and missing-file behavior. |
cmd/cloudstic/store_profile_test.go |
Add tests for applying profile store overrides to global flags. |
cmd/cloudstic/cmd_profile.go |
Implement profile list/show/new with reference resolution and interactive selection flows. |
cmd/cloudstic/cmd_profile_test.go |
Add tests for profile CRUD, reference validation, and display output. |
cmd/cloudstic/cmd_auth.go |
Implement auth list/show/new/login with token path derivation and provider-specific behavior. |
cmd/cloudstic/cmd_auth_test.go |
Add tests for auth CRUD/login flows and token path derivation. |
cmd/cloudstic/cmd_init.go |
Respect --no-prompt during interactive init password prompting. |
cmd/cloudstic/cmd_key.go |
Respect --no-prompt during password change prompting. |
cmd/cloudstic/usage.go |
Update usage output to include new commands and flags (--no-prompt, profile/auth/store). |
cmd/cloudstic/completion.go |
Extend bash/zsh/fish completions for new commands and flags. |
cmd/cloudstic/completion_test.go |
Update completion tests for new commands/flags. |
docs/user-guide.md |
Document profiles/auth/store commands, backup flags, and env var additions. |
README.md |
Add a “Profiles” quickstart section and link to user guide. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| } | ||
|
|
||
| if a.store != "" { |
Comment on lines
+498
to
+504
| uri, err := r.promptLine("Store URI (e.g. s3://bucket/path, local:/path, sftp://host/path)", "") | ||
| if err != nil { | ||
| return "", r.fail("Failed to read store URI: %v", err) | ||
| } | ||
| if uri == "" { | ||
| return "", r.fail("Store URI is required") | ||
| } |
| # skip flags and their values | ||
| case "${words[i]}" in | ||
| -store|-s3-endpoint|-s3-region|-s3-access-key|-s3-secret-key|-source-sftp-password|-source-sftp-key|-store-sftp-password|-store-sftp-key|-encryption-key|-password|-recovery-key|-kms-key-arn|-kms-region|-kms-endpoint|-source|-google-credentials|-google-token-file|-onedrive-client-id|-onedrive-token-file|-tag|-output|-keep-last|-keep-hourly|-keep-daily|-keep-weekly|-keep-monthly|-keep-yearly|-group-by|-account|-json) | ||
| -store|-profile|-profiles-file|-s3-endpoint|-s3-region|-s3-profile|-s3-access-key|-s3-secret-key|-source-sftp-password|-source-sftp-key|-store-sftp-password|-store-sftp-key|-encryption-key|-password|-recovery-key|-kms-key-arn|-kms-region|-kms-endpoint|-source|-all-profiles|-auth-ref|-google-credentials|-google-token-file|-onedrive-client-id|-onedrive-token-file|-tag|-output|-keep-last|-keep-hourly|-keep-daily|-keep-weekly|-keep-monthly|-keep-yearly|-group-by|-account|-json) |
Comment on lines
+392
to
+435
| func cloneGlobalFlags(src *globalFlags) *globalFlags { | ||
| clone := *src | ||
|
|
||
| store := *src.store | ||
| s3Endpoint := *src.s3Endpoint | ||
| s3Region := *src.s3Region | ||
| s3AccessKey := *src.s3AccessKey | ||
| s3SecretKey := *src.s3SecretKey | ||
| sourceSFTPPassword := *src.sourceSFTPPassword | ||
| sourceSFTPKey := *src.sourceSFTPKey | ||
| storeSFTPPassword := *src.storeSFTPPassword | ||
| storeSFTPKey := *src.storeSFTPKey | ||
| encryptionKey := *src.encryptionKey | ||
| password := *src.password | ||
| recoveryKey := *src.recoveryKey | ||
| kmsKeyARN := *src.kmsKeyARN | ||
| kmsRegion := *src.kmsRegion | ||
| kmsEndpoint := *src.kmsEndpoint | ||
| disablePackfile := *src.disablePackfile | ||
| prompt := *src.prompt | ||
| verbose := *src.verbose | ||
| quiet := *src.quiet | ||
| debug := *src.debug | ||
|
|
||
| clone.store = &store | ||
| clone.s3Endpoint = &s3Endpoint | ||
| clone.s3Region = &s3Region | ||
| clone.s3AccessKey = &s3AccessKey | ||
| clone.s3SecretKey = &s3SecretKey | ||
| clone.sourceSFTPPassword = &sourceSFTPPassword | ||
| clone.sourceSFTPKey = &sourceSFTPKey | ||
| clone.storeSFTPPassword = &storeSFTPPassword | ||
| clone.storeSFTPKey = &storeSFTPKey | ||
| clone.encryptionKey = &encryptionKey | ||
| clone.password = &password | ||
| clone.recoveryKey = &recoveryKey | ||
| clone.kmsKeyARN = &kmsKeyARN | ||
| clone.kmsRegion = &kmsRegion | ||
| clone.kmsEndpoint = &kmsEndpoint | ||
| clone.disablePackfile = &disablePackfile | ||
| clone.prompt = &prompt | ||
| clone.verbose = &verbose | ||
| clone.quiet = &quiet | ||
| clone.debug = &debug |
| "-profiles-file", | ||
| "-profile", "-all-profiles", | ||
| "-auth-ref", | ||
| "-auth-ref", |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
storesandauthentries and profile-aware backup execution.What Changes
internal/engine/profiles.goclient.go(LoadProfilesFile,SaveProfilesFile)cloudstic profile {list,show,new}cloudstic auth {new,list,show,login}cloudstic store {list,show,new}-profile <name>-all-profiles-auth-ref <name>-profiles-file <path>cmd/cloudstic/cmd_backup.gocmd/cloudstic/completion.gocmd/cloudstic/usage.godocs/user-guide.md,README.mdrfcs/0010-backup-profiles.mdrfcs/README.mdBehavior Notes
-profileand-all-profilesare mutually exclusive.-all-profilesruns enabled profiles sequentially and reports aggregate failure if any profile fails.*_env) rather than plaintext by default.Testing
cmd/cloudstic/cmd_profile_test.gocmd/cloudstic/cmd_auth_test.gocmd/cloudstic/cmd_store_test.gocmd/cloudstic/cmd_backup_profile_test.gointernal/engine/profiles_test.goTracking
rfcs/0010-backup-profiles.md