feat(environment): deployment environment management for #381 / D-44 - #859
Merged
Nanle-code merged 2 commits intoAug 31, 2026
Merged
Conversation
… / D-44 Closes Nanle-code#381. Summary ------- Issue Nanle-code#381 asked for environment management covering dev/staging/ production deployment environments: environment configuration, environment-specific settings, deployment promotion, environment isolation, configuration validation, and an environment dashboard. Traced the existing code first: `Config.networks` (see docs/CONFIGURATION.md) already answers "where do I connect" for a given blockchain network (Horizon/Soroban RPC endpoints), with a mature, pure, well-tested overlay/validation system (`merge_configs`/`validate_config`/`validate_network_exists`). What did not exist anywhere in the codebase was a first-class "deployment environment" concept — no `Environment` type, no notion of dev vs. staging vs. production, no promotion pipeline between them. This is a genuinely new, additive feature, built as a thin layer on top of the existing network/wallet config and `deploy_history` infrastructure rather than duplicating either. New files --------- src/utils/environment.rs - `EnvironmentTier`: a closed `Dev`/`Staging`/`Production` enum (not an open string) so a mistyped tier name is a compile-time impossibility, with `previous()` encoding the one-step promotion order. - `EnvironmentConfig`: a named binding of `{tier, network, wallet}` plus environment-specific settings — currently `require_confirmation` (defaults to `true` for `Production`) and an optional description. - Configuration validation (`validate_environment`): the target network must exist (built-in or configured — reuses `config:: validate_network_exists`, the pure variant the config docs specifically recommend for this), and if a wallet is named it must exist *and* be provisioned on the same network the environment targets, so a production environment can't silently end up signing with a wallet meant for testnet. - Environment isolation (`check_isolation`, pure): flags when two environments share both the same network *and* the same wallet — the situation where a deploy meant for one would actually affect the other, defeating the point of having separate environments. Sharing only a network (different wallets) or only a wallet across networks is fine and not flagged. - Deployment promotion (`promote`): takes the last successful deployment recorded against the source environment's network and registers its *exact* `wasm_hash` as a new, pending deployment against the target environment's network, linked via `previous_id` — so what was validated in staging is provably the same bytes reaching production, not a rebuild that merely looks the same. Enforces one-step-forward tier order (dev -> staging -> production; skipping a stage is rejected) and isolation between source and target before promoting. Like the existing `deployments rollback` command and Nanle-code#383's rollback automation, this only *records* intent — the actual `stellar contract deploy`/`upgrade` still runs through the normal `starforge deploy --execute` path against the target network. - Persistence mirrors `deploy_history.rs`'s exact pattern: a JSON array at `~/.starforge/environments.json` via `config::config_dir()`. - 18 unit tests, all against pure functions (tier ordering, promotion order, isolation, config defaults) — none touch the real `~/.starforge` directory, matching this codebase's own established precedent (see docs/CONFIGURATION.md's "Pure API" section) of keeping file-I/O-coupled functions out of automated tests. src/commands/environment.rs - New `starforge environment` subcommand group: `add`, `list`, `show`, `remove`, `validate`, `promote`, `dashboard` — styled after the existing `starforge deployments` command group (same `p::` output helpers, same `dialoguer::Confirm` pattern for `promote`'s confirmation gate on environments with `require_confirmation` set). - `dashboard` (the issue's sixth item) shows every registered environment, its tier/network, its last successful deployment (via `deploy_history::last_successful`), and any isolation violation against its siblings — the same "at a glance" shape as `starforge deployments dashboard`. - `validate` runs configuration validation and isolation checking against one or all environments and exits non-zero if any fail, usable directly in CI. - 2 unit tests on `AddArgs`'s tier-string parsing. Wiring (existing files touched) -------------------------------- - src/main.rs: added the `Commands::Environment(...)` variant (`#[command(subcommand)]`, following the exact pattern used for `Deployments`/`Config`/`Network`) and its two dispatch match arms — 5 lines total. `commands::environment::handle` is synchronous, so its dispatch arm has no `.await`, matching the existing precedent for e.g. `Commands::AiNavigate`. - src/commands/mod.rs / src/utils/mod.rs: one `pub mod environment;` each, alphabetically placed among the existing declarations. - Diffed each of these three files against a fresh fetch of `Nanle-code/StarForge`'s current master before and after editing to confirm the diff is exactly these additions and nothing else — one of my own fetches of utils/mod.rs was truncated mid-download earlier in this process (caught by re-fetching and diffing rather than trusting the first copy), so I re-verified all three wiring files this way before committing. Acceptance criteria -------------------- - Environment configuration works: `EnvironmentConfig` + `starforge environment add`, covered by tests on tier parsing/defaults. - Environment-specific settings: `require_confirmation` (production-only by default), enforced in `promote`'s CLI handler. - Deployment promotion: `environment::promote` + `starforge environment promote`, covered by tier-order tests. - Environment isolation: `check_isolation`, covered by 5 tests including same-network/different-wallet (fine), same-network/ same-wallet (violation), no-wallet-configured, and self-comparison boundaries. - Configuration validation: `validate_environment`, reusing `config::validate_network_exists`. - Environment dashboard: `starforge environment dashboard`. Validation ---------- This is a 150+ command Rust workspace and, as with Nanle-code#383, I was not able to run a full `cargo build`/`cargo test` pass in this environment in reasonable time. I cross-checked every new call (`DeployRecord:: new`, `deploy_history::last_successful`/`record_deployment`, `config:: validate_network_exists`/`load`, `WalletEntry.network`) against the exact existing signatures and field names in `deploy_history.rs` and `config.rs`, and checked brace balance and the three wiring-file diffs programmatically rather than guessing. Please still run `cargo test` and `cargo clippy --all-targets -- -D warnings` before merging. Note on assignment: this issue is assigned to another contributor (@devgbmuyiwa) under the Stellar Wave Program, with a due date that has already passed — this commit is authored as devgbmuyiwa directly, at their request, after they added the necessary collaborator access.
|
@devgbmuyiwa Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Collaborator
|
@devgbmuyiwa Please fix the CI check failures!! |
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.
Closes #381.
Summary
Issue #381 asked for environment management covering dev/staging/ production deployment environments: environment configuration, environment-specific settings, deployment promotion, environment isolation, configuration validation, and an environment dashboard.
Traced the existing code first:
Config.networks(see docs/CONFIGURATION.md) already answers "where do I connect" for a given blockchain network (Horizon/Soroban RPC endpoints), with a mature, pure, well-tested overlay/validation system (merge_configs/validate_config/validate_network_exists). What did not exist anywhere in the codebase was a first-class "deployment environment" concept — noEnvironmenttype, no notion of dev vs. staging vs. production, no promotion pipeline between them. This is a genuinely new, additive feature, built as a thin layer on top of the existing network/wallet config anddeploy_historyinfrastructure rather than duplicating either.New files
src/utils/environment.rs
EnvironmentTier: a closedDev/Staging/Productionenum (not an open string) so a mistyped tier name is a compile-time impossibility, withprevious()encoding the one-step promotion order.EnvironmentConfig: a named binding of{tier, network, wallet}plus environment-specific settings — currentlyrequire_confirmation(defaults totrueforProduction) and an optional description.validate_environment): the target network must exist (built-in or configured — reusesconfig:: validate_network_exists, the pure variant the config docs specifically recommend for this), and if a wallet is named it must exist and be provisioned on the same network the environment targets, so a production environment can't silently end up signing with a wallet meant for testnet.check_isolation, pure): flags when two environments share both the same network and the same wallet — the situation where a deploy meant for one would actually affect the other, defeating the point of having separate environments. Sharing only a network (different wallets) or only a wallet across networks is fine and not flagged.promote): takes the last successful deployment recorded against the source environment's network and registers its exactwasm_hashas a new, pending deployment against the target environment's network, linked viaprevious_id— so what was validated in staging is provably the same bytes reaching production, not a rebuild that merely looks the same. Enforces one-step-forward tier order (dev -> staging -> production; skipping a stage is rejected) and isolation between source and target before promoting. Like the existingdeployments rollbackcommand and D-46: Implement Contract Deployment Rollback Automation #383's rollback automation, this only records intent — the actualstellar contract deploy/upgradestill runs through the normalstarforge deploy --executepath against the target network.deploy_history.rs's exact pattern: a JSON array at~/.starforge/environments.jsonviaconfig::config_dir().~/.starforgedirectory, matching this codebase's own established precedent (see docs/CONFIGURATION.md's "Pure API" section) of keeping file-I/O-coupled functions out of automated tests.src/commands/environment.rs
starforge environmentsubcommand group:add,list,show,remove,validate,promote,dashboard— styled after the existingstarforge deploymentscommand group (samep::output helpers, samedialoguer::Confirmpattern forpromote's confirmation gate on environments withrequire_confirmationset).dashboard(the issue's sixth item) shows every registered environment, its tier/network, its last successful deployment (viadeploy_history::last_successful), and any isolation violation against its siblings — the same "at a glance" shape asstarforge deployments dashboard.validateruns configuration validation and isolation checking against one or all environments and exits non-zero if any fail, usable directly in CI.AddArgs's tier-string parsing.Wiring (existing files touched)
Commands::Environment(...)variant (#[command(subcommand)], following the exact pattern used forDeployments/Config/Network) and its two dispatch match arms — 5 lines total.commands::environment::handleis synchronous, so its dispatch arm has no.await, matching the existing precedent for e.g.Commands::AiNavigate.pub mod environment;each, alphabetically placed among the existing declarations.Nanle-code/StarForge's current master before and after editing to confirm the diff is exactly these additions and nothing else — one of my own fetches of utils/mod.rs was truncated mid-download earlier in this process (caught by re-fetching and diffing rather than trusting the first copy), so I re-verified all three wiring files this way before committing.Acceptance criteria
EnvironmentConfig+starforge environment add, covered by tests on tier parsing/defaults.require_confirmation(production-only by default), enforced inpromote's CLI handler.environment::promote+starforge environment promote, covered by tier-order tests.check_isolation, covered by 5 tests including same-network/different-wallet (fine), same-network/ same-wallet (violation), no-wallet-configured, and self-comparison boundaries.validate_environment, reusingconfig::validate_network_exists.starforge environment dashboard.Validation
This is a 150+ command Rust workspace and, as with #383, I was not able to run a full
cargo build/cargo testpass in this environment in reasonable time. I cross-checked every new call (DeployRecord:: new,deploy_history::last_successful/record_deployment,config:: validate_network_exists/load,WalletEntry.network) against the exact existing signatures and field names indeploy_history.rsandconfig.rs, and checked brace balance and the three wiring-file diffs programmatically rather than guessing. Please still runcargo testandcargo clippy --all-targets -- -D warningsbefore merging.Note on assignment: this issue is assigned to another contributor (@devgbmuyiwa) under the Stellar Wave Program, with a due date that has already passed — this commit is authored as devgbmuyiwa directly, at their request, after they added the necessary collaborator access.
Description
Brief description of what this PR does and why.
Closes #(issue number)
Type of Change
Changes Made
Testing
How has this been tested?
Describe the tests you ran and how to reproduce them.
Test Coverage
Describe what scenarios have been tested:
Code Quality Checklist
cargo fmt)cargo clippy -- -D warnings)Breaking Changes
If checked, describe the breaking changes and migration path:
Documentation
Screenshots (if applicable)
Add screenshots or GIFs for UI changes.
Additional Context
Add any other context about the PR here.
Note: Make sure all tests pass locally before submitting:
cargo test cargo fmt --all cargo clippy -- -D warnings