Skip to content

Commit 953d5df

Browse files
committed
feat(env): add environment diagnostics command
1 parent bf1e5fe commit 953d5df

11 files changed

Lines changed: 1418 additions & 0 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
*
3+
* @file EnvCommand.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*/
13+
#ifndef VIX_ENV_COMMAND_HPP
14+
#define VIX_ENV_COMMAND_HPP
15+
16+
#include <string>
17+
#include <vector>
18+
19+
namespace vix::commands
20+
{
21+
/**
22+
* @brief Environment management command.
23+
*
24+
* Provides environment diagnostics for project and production `.env`
25+
* configuration.
26+
*/
27+
class EnvCommand
28+
{
29+
public:
30+
/**
31+
* @brief Run the env command.
32+
*
33+
* @param args Command-line arguments.
34+
* @return Process exit code.
35+
*/
36+
static int run(const std::vector<std::string> &args);
37+
38+
/**
39+
* @brief Print env command help.
40+
*
41+
* @return Process exit code.
42+
*/
43+
static int help();
44+
};
45+
}
46+
47+
#endif
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
*
3+
* @file EnvChecker.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*/
13+
#ifndef VIX_CLI_ENV_CHECKER_HPP
14+
#define VIX_CLI_ENV_CHECKER_HPP
15+
16+
#include <vix/cli/commands/env/EnvTypes.hpp>
17+
18+
namespace vix::commands::env::checker
19+
{
20+
/**
21+
* @brief Check project environment files and production env consistency.
22+
*
23+
* @param cfg Loaded environment configuration.
24+
* @param options Runtime env options.
25+
* @return Process exit code.
26+
*/
27+
int check(
28+
const EnvConfig &cfg,
29+
const EnvOptions &options);
30+
31+
/**
32+
* @brief Build a structured environment check result.
33+
*
34+
* @param cfg Loaded environment configuration.
35+
* @param options Runtime env options.
36+
* @return Environment check result.
37+
*/
38+
EnvCheckResult analyze(
39+
const EnvConfig &cfg,
40+
const EnvOptions &options);
41+
}
42+
43+
#endif
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
*
3+
* @file EnvConfig.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*/
13+
#ifndef VIX_CLI_ENV_CONFIG_HPP
14+
#define VIX_CLI_ENV_CONFIG_HPP
15+
16+
#include <vix/cli/commands/env/EnvTypes.hpp>
17+
18+
#include <filesystem>
19+
#include <map>
20+
#include <string>
21+
22+
namespace vix::commands::env
23+
{
24+
/**
25+
* @brief Load environment configuration for the current project.
26+
*
27+
* Reads:
28+
* - `.env`
29+
* - `.env.example`
30+
* - `production.env.required` from `vix.json`
31+
* - systemd Environment values when production mode is enabled
32+
*
33+
* @param options Runtime env options.
34+
* @return Loaded environment configuration.
35+
*/
36+
EnvConfig load_env_config(const EnvOptions &options);
37+
38+
/**
39+
* @brief Parse a dotenv-style file.
40+
*
41+
* @param path Env file path.
42+
* @return Parsed env file data.
43+
*/
44+
EnvFileData read_env_file(const std::filesystem::path &path);
45+
46+
/**
47+
* @brief Parse a raw systemd Environment property.
48+
*
49+
* @param raw Raw value returned by `systemctl show -p Environment --value`.
50+
* @return Parsed key/value map.
51+
*/
52+
std::map<std::string, std::string> parse_systemd_environment(
53+
const std::string &raw);
54+
55+
/**
56+
* @brief Check whether an env key looks sensitive.
57+
*
58+
* @param key Environment variable name.
59+
* @return true if the key should be treated as secret.
60+
*/
61+
bool is_secret_key(const std::string &key);
62+
}
63+
64+
#endif
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
*
3+
* @file EnvOutput.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*/
13+
#ifndef VIX_CLI_ENV_OUTPUT_HPP
14+
#define VIX_CLI_ENV_OUTPUT_HPP
15+
16+
#include <vix/cli/commands/env/EnvTypes.hpp>
17+
18+
#include <iosfwd>
19+
#include <string>
20+
21+
namespace vix::commands::env::output
22+
{
23+
/**
24+
* @brief Print environment check summary.
25+
*
26+
* @param out Output stream.
27+
* @param cfg Loaded environment configuration.
28+
* @param options Runtime env options.
29+
*/
30+
void print_summary(
31+
std::ostream &out,
32+
const EnvConfig &cfg,
33+
const EnvOptions &options);
34+
35+
/**
36+
* @brief Print one environment variable report item.
37+
*
38+
* @param out Output stream.
39+
* @param variable Environment variable report item.
40+
* @param options Runtime env options.
41+
*/
42+
void print_variable(
43+
std::ostream &out,
44+
const EnvVariable &variable,
45+
const EnvOptions &options);
46+
47+
/**
48+
* @brief Print a section title.
49+
*
50+
* @param out Output stream.
51+
* @param label Section label.
52+
*/
53+
void section(
54+
std::ostream &out,
55+
const std::string &label);
56+
57+
/**
58+
* @brief Print a successful environment message.
59+
*
60+
* @param out Output stream.
61+
* @param message Message to print.
62+
*/
63+
void ok(
64+
std::ostream &out,
65+
const std::string &message);
66+
67+
/**
68+
* @brief Print an environment warning message.
69+
*
70+
* @param out Output stream.
71+
* @param message Message to print.
72+
*/
73+
void warn(
74+
std::ostream &out,
75+
const std::string &message);
76+
77+
/**
78+
* @brief Print an environment error message.
79+
*
80+
* @param out Output stream.
81+
* @param message Message to print.
82+
*/
83+
void error(
84+
std::ostream &out,
85+
const std::string &message);
86+
87+
/**
88+
* @brief Print a fix suggestion.
89+
*
90+
* @param out Output stream.
91+
* @param message Fix suggestion.
92+
*/
93+
void fix(
94+
std::ostream &out,
95+
const std::string &message);
96+
97+
/**
98+
* @brief Mask or display an environment value according to options.
99+
*
100+
* @param variable Environment variable report item.
101+
* @param options Runtime env options.
102+
* @return Display-safe value.
103+
*/
104+
std::string display_value(
105+
const EnvVariable &variable,
106+
const EnvOptions &options);
107+
}
108+
109+
#endif
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
*
3+
* @file EnvTypes.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*/
13+
#ifndef VIX_CLI_ENV_TYPES_HPP
14+
#define VIX_CLI_ENV_TYPES_HPP
15+
16+
#include <filesystem>
17+
#include <map>
18+
#include <set>
19+
#include <string>
20+
#include <vector>
21+
22+
namespace vix::commands::env
23+
{
24+
/**
25+
* @brief Runtime options for `vix env`.
26+
*/
27+
struct EnvOptions
28+
{
29+
/**
30+
* @brief Validate production environment requirements.
31+
*/
32+
bool production{false};
33+
34+
/**
35+
* @brief Mask values when printing them.
36+
*/
37+
bool masked{true};
38+
39+
/**
40+
* @brief Print values explicitly. Secrets stay masked unless unsafe output
41+
* is enabled later.
42+
*/
43+
bool showValues{false};
44+
};
45+
46+
/**
47+
* @brief Parsed key/value environment file.
48+
*/
49+
struct EnvFileData
50+
{
51+
std::filesystem::path path{};
52+
bool exists{false};
53+
std::map<std::string, std::string> values{};
54+
};
55+
56+
/**
57+
* @brief Environment configuration loaded from project files and production config.
58+
*/
59+
struct EnvConfig
60+
{
61+
/**
62+
* @brief Application name.
63+
*/
64+
std::string appName{"vix-app"};
65+
66+
/**
67+
* @brief Project root.
68+
*/
69+
std::filesystem::path projectDir{};
70+
71+
/**
72+
* @brief `.env` file data.
73+
*/
74+
EnvFileData env{};
75+
76+
/**
77+
* @brief `.env.example` file data.
78+
*/
79+
EnvFileData example{};
80+
81+
/**
82+
* @brief Required production environment variables.
83+
*/
84+
std::set<std::string> requiredProductionKeys{};
85+
86+
/**
87+
* @brief Environment variables exposed by systemd.
88+
*/
89+
std::map<std::string, std::string> systemdEnvironment{};
90+
91+
/**
92+
* @brief systemd service name used for production environment comparison.
93+
*/
94+
std::string serviceName{};
95+
};
96+
97+
/**
98+
* @brief A single environment variable report item.
99+
*/
100+
struct EnvVariable
101+
{
102+
std::string name{};
103+
std::string value{};
104+
bool presentInEnv{false};
105+
bool presentInExample{false};
106+
bool presentInSystemd{false};
107+
bool required{false};
108+
bool secret{false};
109+
};
110+
111+
/**
112+
* @brief Result of an environment check.
113+
*/
114+
struct EnvCheckResult
115+
{
116+
bool ok{true};
117+
std::vector<EnvVariable> variables{};
118+
std::vector<std::string> missingFromEnv{};
119+
std::vector<std::string> missingFromExample{};
120+
std::vector<std::string> missingRequiredProduction{};
121+
std::vector<std::string> systemdDiffers{};
122+
};
123+
}
124+
125+
#endif

0 commit comments

Comments
 (0)