Skip to content

feat(environment): deployment environment management for #381 / D-44 - #859

Merged
Nanle-code merged 2 commits into
Nanle-code:masterfrom
devgbmuyiwa:fix/381-environment-management
Aug 31, 2026
Merged

feat(environment): deployment environment management for #381 / D-44#859
Nanle-code merged 2 commits into
Nanle-code:masterfrom
devgbmuyiwa:fix/381-environment-management

Conversation

@devgbmuyiwa

Copy link
Copy Markdown

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 — 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 D-46: Implement Contract Deployment Rollback Automation #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 #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.

Description

Brief description of what this PR does and why.

Closes #(issue number)

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Changes Made

  • Change 1
  • Change 2
  • Change 3

Testing

How has this been tested?

Describe the tests you ran and how to reproduce them.

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed

Test Coverage

Describe what scenarios have been tested:

  • Happy path:
  • Edge cases:
  • Error handling:

Code Quality Checklist

  • My code follows the style guidelines of this project (cargo fmt)
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings (cargo clippy -- -D warnings)
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • The CI checks pass (format, clippy, tests)

Breaking Changes

  • This PR introduces breaking changes

If checked, describe the breaking changes and migration path:

Documentation

  • README.md updated
  • DEVELOPER_GUIDE.md updated (if applicable)
  • API_REFERENCE.md updated (if applicable)
  • No documentation changes needed

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

… / 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.
@drips-wave

drips-wave Bot commented Aug 28, 2026

Copy link
Copy Markdown

@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! 🚀

Learn more about application limits

@Manuelshub

Copy link
Copy Markdown
Collaborator

@devgbmuyiwa Please fix the CI check failures!!

@Nanle-code
Nanle-code merged commit 2eb1cdc into Nanle-code:master Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

D-44: Implement Contract Deployment Environment Management

3 participants