Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(e2e): handle uniqueid & new e2e github action workflow #91

Merged
merged 1 commit into from
Aug 11, 2023
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
66 changes: 66 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: e2e

on:
workflow_dispatch:
inputs:
Branch:
description: The branch to use to run end-to-end tests
required: true
default: develop
type: string
Url:
description: The target environment API URL
required: true
default: https://ibmrpaqa2api.wdgautomation.com/v1.0/
type: string
Region:
description: The target environment Region
required: true
default: QA2_IBMRPA
type: string
Tenant:
description: The target environment Tenant
required: true
default: 5000
type: number
Username:
description: The target environment Username
required: true
type: string
Password:
description: The target environment Password
required: true
type: string

jobs:
e2e:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.Branch }}
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: Build
run: dotnet publish ./src/Joba.IBM.RPA.Cli/Joba.IBM.RPA.Cli.csproj -c Release -f net7.0 -r win-x64 -p:PublishSingleFile=true -o ./publish --self-contained
- name: e2e tests
run: dotnet test ./src/Tests/Joba.IBM.RPA.Cli.Tests --filter "Category=e2e" --verbosity normal
env:
RPA_EXECUTABLE_PATH: ${{github.workspace}}/publish/rpa.exe
E2E_SOURCE_URL: ${{ vars.E2E_SOURCE_URL }}
E2E_SOURCE_REGION: ${{ vars.E2E_SOURCE_REGION }}
E2E_SOURCE_TENANT: ${{ vars.E2E_SOURCE_TENANT }}
E2E_SOURCE_USERNAME: ${{ vars.E2E_SOURCE_USERNAME }}
RPA_SECRET_source: ${{ secrets.DEV_TENANT_PASSWORD }}
E2E_TARGET_URL: ${{ inputs.Url }}
E2E_TARGET_REGION: ${{ inputs.Region }}
E2E_TARGET_TENANT: ${{ inputs.Tenant }}
E2E_TARGET_USERNAME: ${{ inputs.Username }}
RPA_SECRET_target: ${{ secrets.Password }}
E2E_PACKAGE_URL: ${{ vars.E2E_PACKAGE_URL }}
E2E_PACKAGE_REGION: ${{ vars.E2E_PACKAGE_REGION }}
E2E_PACKAGE_TENANT: ${{ vars.E2E_PACKAGE_TENANT }}
E2E_PACKAGE_USERNAME: ${{ vars.E2E_PACKAGE_USERNAME }}
RPA_SECRET_package: ${{ secrets.JOBA_TENANT_PASSWORD }}
18 changes: 15 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,21 @@ jobs:
run: dotnet test ./src/Tests/Joba.IBM.RPA.Cli.Tests --filter "Category=e2e" --verbosity normal
env:
RPA_EXECUTABLE_PATH: ${{github.workspace}}/publish/rpa.exe
RPA_SECRET_dev: ${{ secrets.DEV_TENANT_PASSWORD }}
RPA_SECRET_qa: ${{ secrets.QA_TENANT_PASSWORD }}
RPA_SECRET_joba: ${{ secrets.JOBA_TENANT_PASSWORD }}
E2E_SOURCE_URL: ${{ vars.E2E_SOURCE_URL }}
E2E_SOURCE_REGION: ${{ vars.E2E_SOURCE_REGION }}
E2E_SOURCE_TENANT: ${{ vars.E2E_SOURCE_TENANT }}
E2E_SOURCE_USERNAME: ${{ vars.E2E_SOURCE_USERNAME }}
RPA_SECRET_source: ${{ secrets.DEV_TENANT_PASSWORD }}
E2E_TARGET_URL: ${{ vars.E2E_TARGET_URL }}
E2E_TARGET_REGION: ${{ vars.E2E_TARGET_REGION }}
E2E_TARGET_TENANT: ${{ vars.E2E_TARGET_TENANT }}
E2E_TARGET_USERNAME: ${{ vars.E2E_TARGET_USERNAME }}
RPA_SECRET_target: ${{ secrets.QA_TENANT_PASSWORD }}
E2E_PACKAGE_URL: ${{ vars.E2E_PACKAGE_URL }}
E2E_PACKAGE_REGION: ${{ vars.E2E_PACKAGE_REGION }}
E2E_PACKAGE_TENANT: ${{ vars.E2E_PACKAGE_TENANT }}
E2E_PACKAGE_USERNAME: ${{ vars.E2E_PACKAGE_USERNAME }}
RPA_SECRET_package: ${{ secrets.JOBA_TENANT_PASSWORD }}
- name: Github release
shell: pwsh
run: |
Expand Down
7 changes: 4 additions & 3 deletions src/Joba.IBM.RPA.Cli/Client/RpaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal static JsonSerializerOptions CreateJsonSerializerOptions()
@default.Converters.Add(new WalVersionJsonConverter());
@default.Converters.Add(new AuthenticationMethodJsonConverter());
@default.Converters.Add(new DeploymentOptionJsonConverter());
@default.Converters.Add(new UniqueIdJsonConverter());
return @default;
}

Expand Down Expand Up @@ -272,7 +273,7 @@ public async Task<ServerProject> CreateOrUpdateAsync(string name, string descrip
{
var project = (await SearchAsync(name, 1, cancellation)).FirstOrDefault();
if (project == null)
return await CreateAsync(name, name.Replace(" ", "_"), description, cancellation);
return await CreateAsync(name, new UniqueId(name), description, cancellation);

if (project.Name != name || project.Description != description)
return await UpdateAsync(project.Id, name, description, cancellation);
Expand All @@ -287,7 +288,7 @@ private async Task<IEnumerable<ServerProject>> SearchAsync(string name, int limi
return response.Results;
}

private async Task<ServerProject> CreateAsync(string name, string uniqueId, string description, CancellationToken cancellation)
private async Task<ServerProject> CreateAsync(string name, UniqueId uniqueId, string description, CancellationToken cancellation)
{
var url = $"{CultureInfo.CurrentCulture.Name}/project";
var project = new { Name = name, Description = description, TechnicalName = uniqueId };
Expand Down Expand Up @@ -344,7 +345,7 @@ private async Task<IEnumerable<ServerBotSearch>> SearchAsync(Guid projectId, str
return response.Results;
}

record ServerBotSearch(Guid Id, string Name, string Description, [property: JsonPropertyName("TechnicalName")] string UniqueId, ScriptVersion ScriptVersion);
record ServerBotSearch(Guid Id, string Name, string Description, [property: JsonPropertyName("TechnicalName")] UniqueId UniqueId, ScriptVersion ScriptVersion);
}

class ComputerGroupResource : IComputerGroupResource
Expand Down
2 changes: 1 addition & 1 deletion src/Joba.IBM.RPA/Deploy/DeployService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ async Task IDeployService.DeployAsync(IProject project, Environment environment,

logger.LogDebug("Creating or updating '{Bot}' bot ({Type})", robot.Name, "unattended");
var computerGroup = await client.ComputerGroup.GetAsync(settings.ComputerGroupName, cancellation);
var serverBot = new ServerBot(serverProject.Id, scriptVersion.ScriptId, scriptVersion.Id, computerGroup.Id, robot.Name, robot.Name.Replace(" ", "_"), string.IsNullOrEmpty(robot.Settings.Description) ? robot.Name : robot.Settings.Description);
var serverBot = new ServerBot(serverProject.Id, scriptVersion.ScriptId, scriptVersion.Id, computerGroup.Id, robot.Name, new UniqueId(robot.Name), string.IsNullOrEmpty(robot.Settings.Description) ? robot.Name : robot.Settings.Description);
await client.Bot.CreateOrUpdateAsync(serverBot, cancellation);
}
else
Expand Down
4 changes: 2 additions & 2 deletions src/Joba.IBM.RPA/IRpaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ public interface IComputerGroupResource
}

public record class ComputerGroup(Guid Id, string Name);
public record class ServerBot(Guid ProjectId, Guid ScriptId, Guid ScriptVersionId, [property: JsonPropertyName("GroupId")] Guid ComputerGroupId, string Name, [property: JsonPropertyName("TechnicalName")] string UniqueId, string Description)
public record class ServerBot(Guid ProjectId, Guid ScriptId, Guid ScriptVersionId, [property: JsonPropertyName("GroupId")] Guid ComputerGroupId, string Name, [property: JsonPropertyName("TechnicalName")] UniqueId UniqueId, string Description)
{
public static ServerBot Copy(ServerBot bot, string uniqueId) =>
public static ServerBot Copy(ServerBot bot, UniqueId uniqueId) =>
new(bot.ProjectId, bot.ScriptId, bot.ScriptVersionId, bot.ComputerGroupId, bot.Name, uniqueId, bot.Description);
}

Expand Down
1 change: 1 addition & 0 deletions src/Joba.IBM.RPA/Json/JsonSerializerOptionsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal static JsonSerializerOptions CreateDefault(DirectoryInfo? workingDirect
@default.Converters.Add(new ParameterLocalRepositoryJsonConverterFactory());
@default.Converters.Add(new RobotsJsonConverterFactory());
@default.Converters.Add(new PropertyOptionsJsonConverter());
@default.Converters.Add(new UniqueIdJsonConverter());
return @default;
}

Expand Down
42 changes: 42 additions & 0 deletions src/Joba.IBM.RPA/UniqueId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace Joba.IBM.RPA
{
/// <summary>
/// Must only contain latin letters (a-z, A-Z), numbers (0-9), underscores ( _ ) and cannot start with a number.
/// </summary>
public struct UniqueId
{
private readonly string uniqueId;

public UniqueId(string name)
{
Original = name;
//TODO: use regex to replace everything except the allowed values.
uniqueId = name.Replace(" ", "_").Replace("-", "_");
}

public string Original { get; }

public override string ToString() => uniqueId;

public static implicit operator string(UniqueId id) => id.uniqueId;
}

public class UniqueIdJsonConverter : JsonConverter<UniqueId>
{
public override UniqueId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string uniqueId;
if (reader.TokenType == JsonTokenType.String)
uniqueId = reader.GetString() ?? throw new JsonException();
else
throw new JsonException();

return new UniqueId(uniqueId);
}

public override void Write(Utf8JsonWriter writer, UniqueId value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
}
41 changes: 34 additions & 7 deletions src/Tests/Joba.IBM.RPA.Cli.Tests/EndToEndTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,42 @@ public EndToEndTest(ITestOutputHelper output)
[Fact]
public async Task CreateAndDeployProject()
{
var projectName = $"MyProject-{DateTimeOffset.UtcNow:ddMMyyyyhhmmss}";
await RunAsync($"project new {projectName}");
await RunAsync("env new dev --url https://us1api.wdgautomation.com/v1.0/ --region US1 --userName [email protected] --tenant 5283");
await RunAsync("env new qa --url https://ibmrpaqa2api.wdgautomation.com/v1.0/ --region QA2_IBMRPA --userName [email protected] --tenant 5000");
await RunAsync("package source joba --url https://us1api.wdgautomation.com/v1.0/ --region US1 --userName [email protected] --tenant 5547");
var parameters = ReadParameters();
await RunAsync($"project new {parameters.ProjectName}");
await RunAsync($"env new source --url {parameters.SourceOptions.ApiUrl} --region {parameters.SourceOptions.Region} --userName {parameters.SourceOptions.Username} --tenant {parameters.SourceOptions.TenantCode}");
await RunAsync($"env new target --url {parameters.TargetOptions.ApiUrl} --region {parameters.TargetOptions.Region} --userName {parameters.TargetOptions.Username} --tenant {parameters.TargetOptions.TenantCode}");
await RunAsync($"package source package --url {parameters.PackageOptions.ApiUrl} --region {parameters.PackageOptions.Region} --userName {parameters.PackageOptions.Username} --tenant {parameters.PackageOptions.TenantCode}");
await RunAsync("package install Joba*");
await RunAsync("pull Assistant* --env dev");
await RunAsync("pull Assistant* --env source");
await RunAsync("bot new Attended --template attended");
await RunAsync("bot new Assistant --template chatbot");
//await RunAsync("bot new Unattended --template unattended"); TODO: we would need to setup computer + computer group

await RunAsync("deploy qa");
await RunAsync("deploy target");
}

private E2eParameters ReadParameters()
{
return new E2eParameters(
$"MyProject-{DateTimeOffset.UtcNow:ddMMyyyyhhmmss}",
new E2eRemoteOptions(
GetAndAssertEnvironmentVariable("E2E_SOURCE_URL"),
GetAndAssertEnvironmentVariable("E2E_SOURCE_REGION"),
Convert.ToInt32(GetAndAssertEnvironmentVariable("E2E_SOURCE_TENANT")),
GetAndAssertEnvironmentVariable("E2E_SOURCE_USERNAME")),
new E2eRemoteOptions(
GetAndAssertEnvironmentVariable("E2E_TARGET_URL"),
GetAndAssertEnvironmentVariable("E2E_TARGET_REGION"),
Convert.ToInt32(GetAndAssertEnvironmentVariable("E2E_TARGET_TENANT")),
GetAndAssertEnvironmentVariable("E2E_TARGET_USERNAME")),
new E2eRemoteOptions(
GetAndAssertEnvironmentVariable("E2E_PACKAGE_URL"),
GetAndAssertEnvironmentVariable("E2E_PACKAGE_REGION"),
Convert.ToInt32(GetAndAssertEnvironmentVariable("E2E_PACKAGE_TENANT")),
GetAndAssertEnvironmentVariable("E2E_PACKAGE_USERNAME")));

static string GetAndAssertEnvironmentVariable(string variable) =>
System.Environment.GetEnvironmentVariable(variable) ?? throw new InvalidOperationException($"The environment variable '{variable}' is required and was not found.");
}

private async Task RunAsync(string arguments)
Expand Down Expand Up @@ -89,5 +113,8 @@ void IDisposable.Dispose()
foreach (var file in walFiles)
file.Delete();
}

record struct E2eParameters(string ProjectName, E2eRemoteOptions SourceOptions, E2eRemoteOptions TargetOptions, E2eRemoteOptions PackageOptions);
record struct E2eRemoteOptions(string ApiUrl, string Region, int TenantCode, string Username);
}
}