1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) 2026 Hamze Ghalebi. All rights reserved.
// Licensed under the Rustlift Non-Commercial Licence v1.0.
//! Command-line entrypoint for the Rustlift deployment agent.
//!
//! This binary initialises structured logging, chains the four pipeline
//! stages, and translates any [`DeployError`] into a human-readable hint
//! before exiting with a non-zero status code.
//!
//! # Learning: Separation of Concerns
//!
//! `main.rs` is intentionally thin. It does three things:
//!
//! 1. **Bootstrap** — set up logging.
//! 2. **Delegate** — call `run()` which chains the pipeline.
//! 3. **Report** — translate errors into user-friendly messages.
//!
//! The actual logic lives in the library crate (`lib.rs`, `pipeline.rs`).
//! This separation means the pipeline can be tested, benchmarked, or
//! embedded in another tool without pulling in the CLI layer.
//!
//! # Environment Variables
//!
//! | Variable | Required | Default |
//! |-------------------------|----------|-----------------------|
//! | `AZURE_SUBSCRIPTION_ID` | **yes** | — |
//! | `APP_NAME` | no | `rust-enterprise-api` |
//! | `AZURE_LOCATION` | no | `eastus` |
//! | `RUST_LOG` | no | `info` |
//!
//! # Usage
//!
//! ```bash
//! export AZURE_SUBSCRIPTION_ID="..."
//! RUST_LOG=debug cargo run --bin rustlift # verbose
//! RUST_LOG=info cargo run --bin rustlift # production
//! ```
use ;
use DeployError;
use ;
/// The async runtime entry point.
///
/// # Learning: `#[tokio::main]`
///
/// This attribute macro transforms the `async fn main()` into a regular
/// `fn main()` that creates a Tokio runtime and blocks on the future.
/// Under the hood, it expands to roughly:
///
/// ```rust,ignore
/// fn main() {
/// tokio::runtime::Runtime::new().unwrap().block_on(async { ... })
/// }
/// ```
///
/// We use the default multi-threaded scheduler, which is appropriate
/// for I/O-bound workloads like HTTP requests and process spawning.
async
/// Chains the four pipeline stages into a single async flow.
///
/// Each method call consumes the current `Pipeline<State>` and produces
/// the next state. This is the **typestate pattern** in action — the
/// compiler will refuse to compile code that calls `.deploy_and_verify()`
/// before `.build_and_package()`.
///
/// # Learning: The `?` Operator
///
/// The `?` at the end of each `.await?` does two things:
///
/// 1. If the result is `Ok(value)`, it unwraps `value` and continues.
/// 2. If the result is `Err(e)`, it returns `Err(e)` from the function
/// immediately — no explicit `match` or `if let` needed.
///
/// This makes the "happy path" read like a simple sequential script,
/// while errors propagate automatically to the caller.
///
/// # Errors
///
/// Returns any [`DeployError`] emitted by any stage of the pipeline.
async