Skip to content
Merged
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
18 changes: 18 additions & 0 deletions .github/cli-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,21 @@ psw -p "uSync|17.0.0" -n MyProject -s MySolution \
--admin-email admin@test.com \
--admin-password "SecurePass123!" \
--auto-run

# Auto-run but skip 'dotnet run' (install + build only, no server start)
psw -d -n MyProject -s MyProject \
-u --database-type SQLite \
--admin-email admin@test.com \
--admin-password "SecurePass123!" \
--auto-run --no-run

# Save script to file without interactive prompts (for programmatic use)
psw -d -n MyProject -s MyProject \
-u --database-type SQLite \
--admin-email admin@test.com \
--admin-password "SecurePass123!" \
-p "Umbraco.Forms" \
--output install.sh --save-only
```

### Command Reference
Expand Down Expand Up @@ -310,7 +325,10 @@ psw --default # Generate default script

```bash
--auto-run # Automatically run the generated script
--no-run # Skip 'dotnet run' from the generated script
--run-dir # Directory to run script in
--output <file> # Output file path for saving the generated script
--save-only # Save script to file (via --output) and exit without prompts
```

#### Template Commands
Expand Down
6 changes: 6 additions & 0 deletions src/PSW.Shared/Models/PackagesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,10 @@ public bool CanIncludeDocker
[Display(Name = "Remove comments")]
public bool RemoveComments { get; set; }
public bool HasQueryString { get; set; }

/// <summary>
/// When true, the generated script will not include the 'dotnet run' command.
/// Used by the CLI --no-run flag for automation scenarios where the server should not be started.
/// </summary>
public bool SkipDotnetRun { get; set; }
}
5 changes: 4 additions & 1 deletion src/PSW.Shared/Services/ScriptGeneratorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ public string GenerateScript(PackagesViewModel model)

outputList.AddRange(GenerateAddPackagesScript(model, renderPackageName));

outputList.AddRange(GenerateRunProjectScript(model, renderPackageName));
if (!model.SkipDotnetRun)
{
outputList.AddRange(GenerateRunProjectScript(model, renderPackageName));
}

if (model.RemoveComments)
{
Expand Down
162 changes: 162 additions & 0 deletions src/PackageCliTool.Tests/CommandLineOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -686,4 +686,166 @@ public void Parse_WithCommunityTemplateAndUnattendedOverrides_ParsesAll()
options.DatabaseType.Should().Be("SqlServer");
options.AdminEmail.Should().Be("custom@example.com");
}

#region Non-Interactive Mode Flags

[Fact]
public void Parse_WithNoRunFlag_SetsNoRun()
{
// Arrange
var args = new[] { "--no-run" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.NoRun.Should().BeTrue();
}

[Fact]
public void Parse_WithSaveOnlyFlag_SetsSaveOnly()
{
// Arrange
var args = new[] { "--save-only" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.SaveOnly.Should().BeTrue();
}

[Fact]
public void Parse_WithOutputFlag_SetsOutputFile()
{
// Arrange
var args = new[] { "--output", "install.sh" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.OutputFile.Should().Be("install.sh");
}

[Fact]
public void Parse_WithNoRunAndAutoRun_SetsBothFlags()
{
// Arrange
var args = new[] { "--auto-run", "--no-run" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.AutoRun.Should().BeTrue();
options.NoRun.Should().BeTrue();
}

[Fact]
public void Parse_WithSaveOnlyAndOutput_SetsBothFlags()
{
// Arrange
var args = new[] { "--output", "install.sh", "--save-only" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.SaveOnly.Should().BeTrue();
options.OutputFile.Should().Be("install.sh");
}

[Fact]
public void HasAnyOptions_WithNoRunFlag_ReturnsTrue()
{
// Arrange
var args = new[] { "--no-run" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.HasAnyOptions().Should().BeTrue();
}

[Fact]
public void HasAnyOptions_WithSaveOnlyFlag_ReturnsTrue()
{
// Arrange
var args = new[] { "--save-only" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.HasAnyOptions().Should().BeTrue();
}

[Fact]
public void HasAnyOptions_WithOutputFlag_ReturnsTrue()
{
// Arrange
var args = new[] { "--output", "install.sh" };

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.HasAnyOptions().Should().BeTrue();
}

[Fact]
public void Parse_WithAllAutomationFlags_ParsesCorrectly()
{
// Arrange
var args = new[]
{
"-d",
"-n", "MyProject",
"-s", "MyProject",
"-u",
"--database-type", "SQLite",
"--admin-email", "admin@test.com",
"--admin-password", "SecurePass1234",
"-p", "Umbraco.Forms",
"--output", "install.sh",
"--save-only",
"--no-run"
};

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.UseDefault.Should().BeTrue();
options.ProjectName.Should().Be("MyProject");
options.SolutionName.Should().Be("MyProject");
options.UseUnattended.Should().BeTrue();
options.DatabaseType.Should().Be("SQLite");
options.AdminEmail.Should().Be("admin@test.com");
options.AdminPassword.Should().Be("SecurePass1234");
options.Packages.Should().Be("Umbraco.Forms");
options.OutputFile.Should().Be("install.sh");
options.SaveOnly.Should().BeTrue();
options.NoRun.Should().BeTrue();
options.HasAnyOptions().Should().BeTrue();
}

[Fact]
public void Parse_WithNoArguments_NewFlagsDefaultToFalse()
{
// Arrange
var args = Array.Empty<string>();

// Act
var options = CommandLineOptions.Parse(args);

// Assert
options.NoRun.Should().BeFalse();
options.SaveOnly.Should().BeFalse();
options.OutputFile.Should().BeNull();
}

#endregion
}
115 changes: 115 additions & 0 deletions src/PackageCliTool.Tests/ScriptModelExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using FluentAssertions;
using PackageCliTool.Extensions;
using PackageCliTool.Models.Api;
using Xunit;

namespace PackageCliTool.Tests;

/// <summary>
/// Unit tests for ScriptModelExtensions.ToViewModel()
/// </summary>
public class ScriptModelExtensionsTests
{
[Fact]
public void ToViewModel_WithSkipDotnetRunTrue_MapsCorrectly()
{
// Arrange
var scriptModel = new ScriptModel
{
TemplateName = "Umbraco.Templates",
ProjectName = "TestProject",
SkipDotnetRun = true
};

// Act
var viewModel = scriptModel.ToViewModel();

// Assert
viewModel.SkipDotnetRun.Should().BeTrue();
}

[Fact]
public void ToViewModel_WithSkipDotnetRunFalse_MapsCorrectly()
{
// Arrange
var scriptModel = new ScriptModel
{
TemplateName = "Umbraco.Templates",
ProjectName = "TestProject",
SkipDotnetRun = false
};

// Act
var viewModel = scriptModel.ToViewModel();

// Assert
viewModel.SkipDotnetRun.Should().BeFalse();
}

[Fact]
public void ToViewModel_WithDefaultScriptModel_SkipDotnetRunIsFalse()
{
// Arrange
var scriptModel = new ScriptModel
{
TemplateName = "Umbraco.Templates",
ProjectName = "TestProject"
};

// Act
var viewModel = scriptModel.ToViewModel();

// Assert
viewModel.SkipDotnetRun.Should().BeFalse();
}

[Fact]
public void ToViewModel_MapsAllProperties()
{
// Arrange
var scriptModel = new ScriptModel
{
TemplateName = "Umbraco.Templates",
TemplateVersion = "14.0.0",
CreateSolutionFile = true,
SolutionName = "MySolution",
ProjectName = "MyProject",
UseUnattendedInstall = true,
DatabaseType = "SQLite",
ConnectionString = "Data Source=umbraco.db",
UserFriendlyName = "Admin",
UserEmail = "admin@test.com",
UserPassword = "password123",
Packages = "uSync",
IncludeStarterKit = true,
StarterKitPackage = "clean",
IncludeDockerfile = true,
IncludeDockerCompose = true,
EnableContentDeliveryApi = true,
SkipDotnetRun = true
};

// Act
var viewModel = scriptModel.ToViewModel();

// Assert
viewModel.TemplateName.Should().Be(scriptModel.TemplateName);
viewModel.TemplateVersion.Should().Be(scriptModel.TemplateVersion);
viewModel.CreateSolutionFile.Should().Be(scriptModel.CreateSolutionFile);
viewModel.SolutionName.Should().Be(scriptModel.SolutionName);
viewModel.ProjectName.Should().Be(scriptModel.ProjectName);
viewModel.UseUnattendedInstall.Should().Be(scriptModel.UseUnattendedInstall);
viewModel.DatabaseType.Should().Be(scriptModel.DatabaseType);
viewModel.ConnectionString.Should().Be(scriptModel.ConnectionString);
viewModel.UserFriendlyName.Should().Be(scriptModel.UserFriendlyName);
viewModel.UserEmail.Should().Be(scriptModel.UserEmail);
viewModel.UserPassword.Should().Be(scriptModel.UserPassword);
viewModel.Packages.Should().Be(scriptModel.Packages);
viewModel.IncludeStarterKit.Should().Be(scriptModel.IncludeStarterKit);
viewModel.StarterKitPackage.Should().Be(scriptModel.StarterKitPackage);
viewModel.IncludeDockerfile.Should().Be(scriptModel.IncludeDockerfile);
viewModel.IncludeDockerCompose.Should().Be(scriptModel.IncludeDockerCompose);
viewModel.EnableContentDeliveryApi.Should().Be(scriptModel.EnableContentDeliveryApi);
viewModel.SkipDotnetRun.Should().Be(scriptModel.SkipDotnetRun);
}
}
Loading