agpm_cli/upgrade/config.rs
1use serde::{Deserialize, Serialize};
2
3/// Configuration settings for AGPM self-update behavior.
4///
5/// `UpgradeConfig` defines how AGPM handles automatic update checking,
6/// backup creation, and security verification during upgrades. These settings
7/// can be configured globally or per-project to control update behavior.
8///
9/// # Configuration Categories
10///
11/// ## Update Timing
12/// - **Startup Checks**: Whether to check for updates when AGPM starts
13/// - **Check Intervals**: How frequently to perform background update checks
14///
15/// ## Safety Settings
16/// - **Automatic Backups**: Whether to create backups before upgrades
17/// - **Checksum Verification**: Whether to verify download integrity
18///
19/// # Default Behavior
20///
21/// The default configuration prioritizes safety and user control:
22/// - No automatic update checking on startup (avoids startup delays)
23/// - 24-hour intervals for update checks (balances freshness with performance)
24/// - Always create backups (enables rollback on failures)
25/// - Always verify checksums (ensures download integrity)
26///
27/// # Examples
28///
29/// ## Using Default Configuration
30/// ```rust,no_run
31/// use agpm_cli::upgrade::config::UpgradeConfig;
32///
33/// let config = UpgradeConfig::default();
34/// assert_eq!(config.check_on_startup, false);
35/// assert_eq!(config.auto_backup, true);
36/// ```
37///
38/// ## Custom Configuration
39/// ```rust,no_run
40/// use agpm_cli::upgrade::config::UpgradeConfig;
41///
42/// let config = UpgradeConfig {
43/// check_on_startup: true,
44/// check_interval: 3600, // 1 hour
45/// auto_backup: true,
46/// verify_checksum: true,
47/// };
48/// ```
49///
50/// # Serialization
51///
52/// This configuration can be serialized to TOML, JSON, or other formats
53/// supported by serde for storage in configuration files.
54///
55/// ## TOML Example
56/// ```toml
57/// [upgrade]
58/// check_on_startup = false
59/// check_interval = 86400
60/// auto_backup = true
61/// verify_checksum = true
62/// ```
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct UpgradeConfig {
65 /// Whether to check for updates when AGPM starts.
66 ///
67 /// When enabled, AGPM will perform a background check for updates every
68 /// time it starts up. This provides the earliest notification of available
69 /// updates but may slightly delay startup time.
70 ///
71 /// # Default: `false`
72 ///
73 /// Disabled by default to avoid slowing down CLI operations. Users can
74 /// manually check for updates using `agpm upgrade --check`.
75 ///
76 /// # Considerations
77 ///
78 /// - **Startup Performance**: Adds network delay to every AGPM invocation
79 /// - **Network Dependency**: May fail or timeout in poor network conditions
80 /// - **Rate Limiting**: Frequent use may hit GitHub API rate limits
81 /// - **User Experience**: Can be intrusive for automated scripts
82 #[serde(default = "default_check_on_startup")]
83 pub check_on_startup: bool,
84
85 /// Interval between automatic update checks in seconds.
86 ///
87 /// Controls how frequently AGPM performs background checks for new versions.
88 /// This setting balances update notification timeliness with network usage
89 /// and API rate limit consumption.
90 ///
91 /// # Default: `86400` (24 hours)
92 ///
93 /// The default 24-hour interval provides daily update notifications while
94 /// being respectful of GitHub's API rate limits.
95 ///
96 /// # Recommended Values
97 ///
98 /// - **3600** (1 hour): For development environments or beta testing
99 /// - **21600** (6 hours): For active development workflows
100 /// - **86400** (1 day): Standard for most users (default)
101 /// - **604800** (1 week): For stable environments with infrequent updates
102 ///
103 /// # Rate Limiting
104 ///
105 /// GitHub allows 60 unauthenticated API requests per hour per IP address.
106 /// Setting intervals below 1 minute may exceed rate limits with heavy usage.
107 #[serde(default = "default_check_interval")]
108 pub check_interval: u64,
109
110 /// Whether to automatically create backups before upgrades.
111 ///
112 /// When enabled, AGPM creates a backup copy of the current binary before
113 /// attempting any upgrade. This enables rollback if the upgrade fails or
114 /// the new version has issues.
115 ///
116 /// # Default: `true`
117 ///
118 /// Enabled by default for maximum safety. Backups use minimal disk space
119 /// and provide crucial recovery capability.
120 ///
121 /// # Backup Process
122 ///
123 /// - Creates a copy with `.backup` suffix in the same directory
124 /// - Preserves file permissions and metadata
125 /// - Automatically removed after successful upgrades
126 /// - Can be restored manually or via `agpm upgrade --rollback`
127 ///
128 /// # Disabling Backups
129 ///
130 /// Consider disabling only in environments where:
131 /// - Disk space is severely constrained
132 /// - File system permissions prevent backup creation
133 /// - Alternative backup/recovery mechanisms are in place
134 /// - Upgrade failures can be resolved through reinstallation
135 #[serde(default = "default_auto_backup")]
136 pub auto_backup: bool,
137
138 /// Whether to verify checksums of downloaded binaries.
139 ///
140 /// When enabled, AGPM verifies the integrity of downloaded binaries by
141 /// comparing their checksums against expected values. This provides
142 /// protection against corrupted downloads and potential security issues.
143 ///
144 /// # Default: `true`
145 ///
146 /// Enabled by default for security and reliability. Checksum verification
147 /// adds minimal overhead but provides important integrity guarantees.
148 ///
149 /// # Security Benefits
150 ///
151 /// - **Download Integrity**: Detects corrupted or incomplete downloads
152 /// - **Tamper Detection**: Identifies potentially modified binaries
153 /// - **Supply Chain Security**: Helps ensure binary authenticity
154 /// - **Network Reliability**: Catches network-induced corruption
155 ///
156 /// # Verification Process
157 ///
158 /// - Downloads expected checksums from GitHub releases
159 /// - Computes actual checksum of downloaded binary
160 /// - Compares checksums before proceeding with installation
161 /// - Aborts upgrade if checksums don't match
162 ///
163 /// # Disabling Verification
164 ///
165 /// Consider disabling only in environments where:
166 /// - Network reliability is extremely poor
167 /// - Checksum information is unavailable from releases
168 /// - Alternative integrity verification is in place
169 /// - Testing scenarios require bypassing verification
170 #[serde(default = "default_verify_checksum")]
171 pub verify_checksum: bool,
172}
173
174impl Default for UpgradeConfig {
175 /// Create an `UpgradeConfig` with safe, conservative defaults.
176 ///
177 /// The default configuration prioritizes safety, reliability, and user control
178 /// over aggressive update checking. This approach:
179 ///
180 /// - Avoids surprising users with automatic behavior
181 /// - Minimizes impact on CLI performance
182 /// - Provides maximum safety during upgrades
183 /// - Respects GitHub API rate limits
184 ///
185 /// # Default Values
186 ///
187 /// - `check_on_startup`: `false` - No startup delays
188 /// - `check_interval`: `86400` (24 hours) - Daily update checks
189 /// - `auto_backup`: `true` - Always create backups for safety
190 /// - `verify_checksum`: `true` - Always verify download integrity
191 ///
192 /// # Examples
193 ///
194 /// ```rust,no_run
195 /// use agpm_cli::upgrade::config::UpgradeConfig;
196 ///
197 /// let config = UpgradeConfig::default();
198 /// assert_eq!(config.check_on_startup, false);
199 /// assert_eq!(config.check_interval, 86400);
200 /// assert_eq!(config.auto_backup, true);
201 /// assert_eq!(config.verify_checksum, true);
202 /// ```
203 fn default() -> Self {
204 Self {
205 check_on_startup: default_check_on_startup(),
206 check_interval: default_check_interval(),
207 auto_backup: default_auto_backup(),
208 verify_checksum: default_verify_checksum(),
209 }
210 }
211}
212
213/// Default value for startup update checking.
214///
215/// Returns `false` to avoid adding network latency to every AGPM invocation.
216/// Users can explicitly enable this or use manual update checking.
217const fn default_check_on_startup() -> bool {
218 false // Default to not checking on startup to avoid slowing down the CLI
219}
220
221/// Default value for update check interval.
222///
223/// Returns `86400` (24 hours) to provide daily update notifications while
224/// being respectful of GitHub API rate limits and user attention.
225const fn default_check_interval() -> u64 {
226 86400 // 24 hours in seconds
227}
228
229/// Default value for automatic backup creation.
230///
231/// Returns `true` to maximize safety during upgrades. Backups enable quick
232/// recovery from failed upgrades and add minimal overhead.
233const fn default_auto_backup() -> bool {
234 true // Always create backups for safety
235}
236
237/// Default value for checksum verification.
238///
239/// Returns `true` to ensure download integrity and provide security against
240/// corrupted or tampered binaries. Verification adds minimal overhead.
241const fn default_verify_checksum() -> bool {
242 true // Always verify checksums for security
243}
244
245impl UpgradeConfig {
246 /// Create a new `UpgradeConfig` with default settings.
247 ///
248 /// This is equivalent to [`Default::default()`] but provides a more
249 /// conventional constructor-style interface for creating configurations.
250 ///
251 /// # Examples
252 ///
253 /// ```rust,no_run
254 /// use agpm_cli::upgrade::config::UpgradeConfig;
255 ///
256 /// // These are equivalent
257 /// let config1 = UpgradeConfig::new();
258 /// let config2 = UpgradeConfig::default();
259 ///
260 /// assert_eq!(config1.check_on_startup, config2.check_on_startup);
261 /// assert_eq!(config1.auto_backup, config2.auto_backup);
262 /// ```
263 ///
264 /// # See Also
265 ///
266 /// - [`Default::default()`] - Alternative way to create default configuration
267 pub fn new() -> Self {
268 Self::default()
269 }
270}