Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,56 @@ The tool supports the following AI models:

---

### Environment Variable Management

The `set-env` command allows you to set environment variables directly from the command line. This is particularly useful for configuring API keys, database URLs, and other settings in development or CI/CD environments.

#### Syntax

```bash
dotnet-aicommitmessage set-env <VARIABLE_NAME=value> [--target <User|Machine>]
```

#### Parameters

| Parameter | Short | Required | Description |
|-----------|-------|----------|-------------|
| `VARIABLE_NAME=value` | - | Yes | The environment variable in `NAME=value` format |
| `--target` | `-t` | No | Target scope: `User` (default) or `Machine` |

#### Target Scopes

| Target | Description | Permissions Required |
|--------|-------------|---------------------|
| `User` | Sets the environment variable for the current user only (default) | Normal user permissions |
| `Machine` | Sets the environment variable system-wide for all users | Administrator (Windows) or sudo (Linux/Mac) |

#### Examples

**Set a variable for the current user (default):**
```bash
dotnet-aicommitmessage set-env MY_API_KEY=sk-abc123xyz
```

**Set a variable with explicit User target:**
```bash
dotnet-aicommitmessage set-env DATABASE_URL=postgresql://localhost:5432/mydb --target User
```

**Set a variable using short option:**
```bash
dotnet-aicommitmessage set-env DEBUG_MODE=true -t User
```

**Set a Machine-level variable (requires admin/sudo):**

On Windows (run Command Prompt or PowerShell as Administrator):
```bash
dotnet-aicommitmessage set-env SYSTEM_CONFIG=production --target Machine
```

---

## Commit message pattern

The training model for the AI used is designed using as reference these guidelines:
Expand Down Expand Up @@ -152,6 +202,7 @@ This tool accepts an argument as the command to execute. Here is a list of avail
| `install-hook` | Installs GIT hooks in the default `.git/hooks` directory or in the custom directory configured in GIT settings. |
| `generate-message` | Generates a commit message based on the current changes (`git diff` context). |
| `set-settings` | Set the OpenAI settings. |
| `set-env` | Set environment variables for User or Machine scope. |
| `help` | Display information about this program. |
| `version` | Display version information. |

Expand Down
2 changes: 1 addition & 1 deletion Src/AiCommitMessage/AiCommitMessage.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
Expand Down
30 changes: 30 additions & 0 deletions Src/AiCommitMessage/Options/SetEnvironmentVariableOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using CommandLine;

namespace AiCommitMessage.Options;

/// <summary>
/// Class SetEnvironmentVariableOptions.
/// </summary>
[Verb("set-env", HelpText = "Set the Environment Variable.")]
public class SetEnvironmentVariableOptions
{
/// <summary>
/// Gets or sets the variable.
/// </summary>
/// <value>The variable.</value>
[Value(0, Required = true, HelpText = "The environment variable in VAR_NAME=value format.")]
public string Variable { get; set; }

/// <summary>
/// Gets or sets the target.
/// </summary>
/// <value>The target.</value>
[Option(
't',
"target",
Required = false,
Default = "User",
HelpText = "The environment variable target (User or Machine). Default is User."
)]
public string Target { get; set; }
}
12 changes: 10 additions & 2 deletions Src/AiCommitMessage/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ internal static class Program
/// <param name="args">An array of strings representing the command-line arguments passed to the application.</param>
/// <remarks>
/// This method utilizes the Parser class to parse command-line arguments into specific options types:
/// <see cref="InstallHookOptions"/>, <see cref="GenerateCommitMessageOptions"/>, and <see cref="SetSettingsOptions"/>.
/// <see cref="InstallHookOptions"/>, <see cref="GenerateCommitMessageOptions"/>, <see cref="SetSettingsOptions"/>, and
/// <see cref="SetEnvironmentVariableOptions"/>.
/// It calls the <c>Run</c> method if the parsing is successful, allowing the application to execute the intended functionality.
/// If the parsing fails, it invokes the <c>HandleErrors</c> method to manage any errors that occurred during parsing.
/// This structure allows for a clean and organized way to handle different command-line options and their corresponding actions.
Expand All @@ -28,7 +29,8 @@ private static void Main(string[] args) =>
.Default.ParseArguments<
InstallHookOptions,
GenerateCommitMessageOptions,
SetSettingsOptions
SetSettingsOptions,
SetEnvironmentVariableOptions
>(args)
.WithParsed(Run)
.WithNotParsed(HandleErrors);
Expand All @@ -51,6 +53,9 @@ private static void Main(string[] args) =>
/// 3. If the options are of type <see cref="SetSettingsOptions"/>, it updates settings by invoking the
/// <see cref="SettingsService.SetSettings"/> method with the provided options.
///
/// 4. If the options are of type <see cref="SetEnvironmentVariableOptions"/>, it sets an environment variable
/// by invoking the <see cref="EnvironmentVariableService.SetEnvironmentVariable"/> method with the provided options.
///
/// If none of these types match, an error message indicating "Invalid command-line arguments." is outputted.
/// This method is designed to facilitate command-line operations by routing the execution flow to the
/// appropriate service based on user input.
Expand All @@ -71,6 +76,9 @@ private static void Run(object options)
case SetSettingsOptions setSettingsOptions:
SettingsService.SetSettings(setSettingsOptions);
break;
case SetEnvironmentVariableOptions setEnvironmentVariableOptions:
EnvironmentVariableService.SetEnvironmentVariable(setEnvironmentVariableOptions);
break;
default:
Output.ErrorLine("Invalid command-line arguments.");
Environment.ExitCode = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Spectre.Console;

namespace AiCommitMessage.Services.Cache
{
Expand All @@ -21,16 +22,16 @@
)
{
string hash = _cacheProvider.GenerateHash(model, branch, authorMessage, diff);
string? cached = await _cacheProvider.LoadAsync(model, hash);

Check warning on line 25 in Src/AiCommitMessage/Services/Cache/CommitMessageCacheService.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 25 in Src/AiCommitMessage/Services/Cache/CommitMessageCacheService.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 25 in Src/AiCommitMessage/Services/Cache/CommitMessageCacheService.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 25 in Src/AiCommitMessage/Services/Cache/CommitMessageCacheService.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 25 in Src/AiCommitMessage/Services/Cache/CommitMessageCacheService.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 25 in Src/AiCommitMessage/Services/Cache/CommitMessageCacheService.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
if (cached != null)
{
Console.WriteLine("\u2705 Loaded from cache.");
AnsiConsole.WriteLine("\u2705 Loaded from cache.");
return cached;
}

string result = await generateFunc();
await _cacheProvider.SaveAsync(model, hash, result);
Console.WriteLine("\ud83d\udcac Cached new result.");
AnsiConsole.WriteLine("\ud83d\udcac Cached new result.");
return result;
}
}
Expand Down
109 changes: 109 additions & 0 deletions Src/AiCommitMessage/Services/EnvironmentVariableService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using AiCommitMessage.Options;
using AiCommitMessage.Utility;

namespace AiCommitMessage.Services;

/// <summary>
/// Service for managing environment variables.
/// </summary>
public static class EnvironmentVariableService
{
/// <summary>
/// Outputs an error message and sets the exit code to 1.
/// </summary>
/// <param name="message">The error message to display.</param>
private static void ErrorLine(string message)
{
Output.ErrorLine(message);
Environment.ExitCode = 1;
}

/// <summary>
/// Sets an environment variable based on the provided options.
/// </summary>
/// <param name="setEnvironmentVariableOptions">The options containing the variable name, value, and target scope.</param>
/// <remarks>
/// This method parses the variable string in the format "VAR_NAME=value" and sets the environment variable
/// to the specified target scope (User or Machine). If no target is specified, it defaults to User scope.
/// Setting environment variables with Machine scope requires administrator privileges on Windows.
/// </remarks>
/// <exception cref="System.Security.SecurityException">Thrown when attempting to set a Machine-level variable without sufficient permissions.</exception>
/// <exception cref="ArgumentException">Thrown when the variable name contains invalid characters.</exception>
public static void SetEnvironmentVariable(
SetEnvironmentVariableOptions setEnvironmentVariableOptions
)
{
if (string.IsNullOrWhiteSpace(setEnvironmentVariableOptions.Variable))
{
ErrorLine("Variable cannot be null or empty.");
return;
}

var variable = setEnvironmentVariableOptions.Variable.Split('=', 2);
if (variable.Length != 2)
{
ErrorLine("Invalid variable format. Please use the format: VAR_NAME=value");
return;
}

var variableName = variable[0].Trim();
var variableValue = variable[1].Trim();
if (string.IsNullOrWhiteSpace(variableName))
{
ErrorLine("Variable name cannot be empty.");
return;
}

EnvironmentVariableTarget envTarget;
if (
string.Equals(
setEnvironmentVariableOptions.Target,
"Machine",
StringComparison.OrdinalIgnoreCase
)
)
{
envTarget = EnvironmentVariableTarget.Machine;
}
else if (
string.Equals(
setEnvironmentVariableOptions.Target,
"User",
StringComparison.OrdinalIgnoreCase
)
)
{
envTarget = EnvironmentVariableTarget.User;
}
else
{
ErrorLine(
$"Invalid target '{setEnvironmentVariableOptions.Target}'. Please use 'User' or 'Machine'."
);
return;
}

try
{
Environment.SetEnvironmentVariable(variableName, variableValue, envTarget);

Output.InfoLine(
$"Environment variable '{variableName}' set to '{variableValue}' for {envTarget} scope."
);
}
catch (System.Security.SecurityException)
{
ErrorLine(
"Permission denied. Setting Machine-level environment variables requires administrator privileges."
);
}
catch (ArgumentException ex)
{
ErrorLine($"Invalid argument: {ex.Message}");
}
catch (Exception ex)
{
ErrorLine($"An error occurred while setting the environment variable: {ex.Message}");
}
}
}
Loading
Loading