Skip to content

feat: Implement initialization command #31

Merged
OGR-67 merged 2 commits into
devfrom
4-feat-init-command-git-pre-commit-hook
Mar 21, 2026
Merged

feat: Implement initialization command #31
OGR-67 merged 2 commits into
devfrom
4-feat-init-command-git-pre-commit-hook

Conversation

@OGR-67

@OGR-67 OGR-67 commented Mar 21, 2026

Copy link
Copy Markdown
Owner

Description

This pull request introduces a configuration system to the CLI, enabling persistent storage of input/output paths and output file names, and adds an interactive init command to simplify project setup. The changes also allow the CLI to read these configuration values by default, while still permitting command-line overrides. Additionally, the PR provides optional integration with Git pre-commit hooks and updates dependency injection and command registration accordingly.

Configuration system and command updates:

  • Added ConfigService (ConfigService.cs, IConfigService.cs) to handle reading and writing shared (config.json) and local (config.local.json) configuration files under the .al2dbml directory. This service is registered for dependency injection. [1] [2] [3]
  • Introduced configuration models: SharedConfig for output settings and LocalConfig for input settings, with sensible defaults. [1] [2]
  • Updated GenerateCommand to use configuration values as defaults for input path, output path, and output file name, falling back to command-line arguments if provided.

New CLI features:

  • Added an interactive init command (InitCommand) that prompts the user for configuration values, saves them, ensures .gitignore is updated, and optionally creates or updates a Git pre-commit hook to run al2dbml generate.
  • Registered the new init command in the CLI application.

These changes streamline project setup and make it easier to maintain consistent configuration across teams and environments.

Closes

closes #4

Copilot AI review requested due to automatic review settings March 21, 2026 07:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a persisted CLI configuration mechanism (shared + local) and adds an interactive init command to scaffold/update those configs, with generate now defaulting to config values unless explicitly overridden by CLI options.

Changes:

  • Added IConfigService/ConfigService plus SharedConfig and LocalConfig models for reading/writing .al2dbml/config.json and .al2dbml/config.local.json.
  • Added init CLI command to prompt for config values, update .gitignore, and optionally install/update a git pre-commit hook.
  • Updated generate command and CLI registration/DI wiring to use configuration defaults.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/AL2DBML.CLI/Services/IConfigService.cs Defines config read/write contract for shared/local config.
src/AL2DBML.CLI/Services/ConfigService.cs Implements JSON-backed config persistence under .al2dbml/.
src/AL2DBML.CLI/Models/SharedConfig.cs Adds shared output configuration model (path/name).
src/AL2DBML.CLI/Models/LocalConfig.cs Adds local input configuration model (path).
src/AL2DBML.CLI/Commands/InitCommand.cs Implements interactive initialization + gitignore/hook integration.
src/AL2DBML.CLI/Commands/GenerateCommand.cs Loads config defaults when CLI options aren’t provided.
src/AL2DBML.CLI/Program.cs Registers new services and init command with Spectre.Console.Cli.
.gitignore Updates ignore patterns for generated outputs and config files.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +105
private static void WritePreCommitHook()
{
const string hookPath = ".git/hooks/pre-commit";
var hookSection = $"{HookStartMarker}\nif command -v al2dbml > /dev/null 2>&1; then\n {HookCommand} || echo \"Warning: al2dbml generate failed, skipping DBML update.\"\nelse\n echo \"Warning: al2dbml not found, skipping DBML update.\"\nfi\n{HookEndMarker}";

string content;
if (File.Exists(hookPath))
{
content = File.ReadAllText(hookPath);
var startIdx = content.IndexOf(HookStartMarker, StringComparison.Ordinal);
var endIdx = content.IndexOf(HookEndMarker, StringComparison.Ordinal);

if (startIdx >= 0 && endIdx >= 0)
content = content[..startIdx] + hookSection + content[(endIdx + HookEndMarker.Length)..];
else
content = content.TrimEnd() + $"\n\n{hookSection}\n";
}
else
{
content = $"#!/bin/sh\n\n{hookSection}\n";
}

File.WriteAllText(hookPath, content);

Copilot AI Mar 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WritePreCommitHook() writes to .git/hooks/pre-commit but doesn’t verify that the repository is a git repo or that .git/hooks exists. Running init outside a git checkout will throw DirectoryNotFoundException. Consider detecting .git/hooks (or .git) first and either skipping hook creation with a warning or creating the directory structure where appropriate.

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 26
app.Configure(config =>
{
config.AddCommand<GenerateCommand>("generate");
config.AddCommand<InitCommand>("init");
});

Copilot AI Mar 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description still contains the placeholder closes #. The repo’s PR validation workflow requires a real closes/fixes/resolves #<issue> reference, so this will likely fail CI until it’s updated.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +27
return JsonSerializer.Deserialize<SharedConfig>(File.ReadAllText(path), JsonOptions);
}

public LocalConfig? LoadLocalConfig()
{
var path = Path.Combine(ConfigDir, LocalConfigFile);
if (!File.Exists(path)) return null;
return JsonSerializer.Deserialize<LocalConfig>(File.ReadAllText(path), JsonOptions);

Copilot AI Mar 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadSharedConfig/LoadLocalConfig will throw (and crash the CLI) if the JSON is invalid/empty or the file is unreadable, since JsonSerializer.Deserialize and File.ReadAllText exceptions aren’t handled. Consider catching JsonException/IOException and either returning null (with a warning) or throwing a more user-friendly exception that the commands can render nicely.

Suggested change
return JsonSerializer.Deserialize<SharedConfig>(File.ReadAllText(path), JsonOptions);
}
public LocalConfig? LoadLocalConfig()
{
var path = Path.Combine(ConfigDir, LocalConfigFile);
if (!File.Exists(path)) return null;
return JsonSerializer.Deserialize<LocalConfig>(File.ReadAllText(path), JsonOptions);
try
{
var json = File.ReadAllText(path);
if (string.IsNullOrWhiteSpace(json)) return null;
return JsonSerializer.Deserialize<SharedConfig>(json, JsonOptions);
}
catch (IOException)
{
// Treat unreadable config as missing
return null;
}
catch (JsonException)
{
// Treat invalid JSON config as missing
return null;
}
}
public LocalConfig? LoadLocalConfig()
{
var path = Path.Combine(ConfigDir, LocalConfigFile);
if (!File.Exists(path)) return null;
try
{
var json = File.ReadAllText(path);
if (string.IsNullOrWhiteSpace(json)) return null;
return JsonSerializer.Deserialize<LocalConfig>(json, JsonOptions);
}
catch (IOException)
{
// Treat unreadable config as missing
return null;
}
catch (JsonException)
{
// Treat invalid JSON config as missing
return null;
}

Copilot uses AI. Check for mistakes.
@OGR-67 OGR-67 merged commit 8ae5aa3 into dev Mar 21, 2026
1 check passed
@OGR-67 OGR-67 deleted the 4-feat-init-command-git-pre-commit-hook branch March 21, 2026 07:21
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.

2 participants