File: WorkflowScripts\DeploymentTestCommandTests.cs
Web Access
Project: src\tests\Infrastructure.Tests\Infrastructure.Tests.csproj (Infrastructure.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.TestUtilities;
using Xunit;
using YamlDotNet.RepresentationModel;
 
namespace Infrastructure.Tests;
 
public sealed class DeploymentTestCommandTests(ITestOutputHelper output)
{
    [Fact]
    public void CommandPrefilterSelectsCandidatesOnMicrosoftPullRequests()
    {
        var condition = Scalar(LoadJob(), "if");
        Assert.Equal(
            "${{ startsWith(github.event.comment.body, '/deployment-test') && github.event.issue.pull_request && github.repository_owner == 'microsoft' }}",
            string.Join(" ", condition.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries)));
    }
 
    [Fact]
    public void DeploymentStepsRequireRepositoryWriteAccess()
    {
        var steps = LoadSteps();
        Assert.Equal("check_permission", Scalar(steps[0], "id"));
        Assert.Equal(3, steps.Length);
        foreach (var step in steps.Skip(1))
        {
            Assert.Equal("steps.check_permission.outputs.has_write_access == 'true'", Scalar(step, "if"));
        }
    }
 
    [Theory]
    [InlineData("write")]
    [InlineData("admin")]
    [InlineData("maintain")]
    [InlineData("read")]
    [InlineData("triage")]
    [InlineData("none")]
    [InlineData("unknown")]
    [InlineData("error-403")]
    [InlineData("error-404")]
    [InlineData("error-500")]
    [RequiresTools(["node"])]
    public async Task PermissionCheckOnlyAllowsRepositoryWriters(string scenario)
        => await RunPermissionCheckAsync(scenario, "/deployment-test", validCommand: true);
 
    [Theory]
    [InlineData("/deployment-test", true)]
    [InlineData("/deployment-test ", true)]
    [InlineData("/deployment-test arguments", true)]
    [InlineData("/deployment-test\n", true)]
    [InlineData("/deployment-test\r", true)]
    [InlineData("/deployment-test\r\nMore text", true)]
    [InlineData("/deployment-test\targuments", true)]
    [InlineData("/DEPLOYMENT-TEST\nMore text", true)]
    [InlineData("/deployment-testing", false)]
    [InlineData("/deployment-test-disabled", false)]
    [InlineData("/deployment-test/extra", false)]
    [InlineData("/deployment-test.", false)]
    [InlineData(" /deployment-test", false)]
    [InlineData("Please run /deployment-test", false)]
    [InlineData("", false)]
    [RequiresTools(["node"])]
    public async Task CommandRequiresEndOfTextOrWhitespace(string body, bool validCommand)
        => await RunPermissionCheckAsync("write", body, validCommand);
 
    private async Task RunPermissionCheckAsync(string scenario, string body, bool validCommand)
    {
        using var workspace = TemporaryWorkspace.Create(output);
        var options = Assert.IsType<YamlMappingNode>(LoadSteps()[0].Children[new YamlScalarNode("with")]);
        var scriptPath = Path.Combine(workspace.Path, "permission-check.js");
        await File.WriteAllTextAsync(scriptPath, Scalar(options, "script"));
        using var node = new NodeCommand(output, nameof(DeploymentTestCommandTests))
            .WithTimeout(TimeSpan.FromMinutes(1));
        var result = await node.ExecuteScriptAsync(
            Path.Combine(RepoRoot.Path, "tests", "Infrastructure.Tests", "WorkflowScripts", "deployment-test-command.harness.mjs"),
            scriptPath,
            scenario,
            body,
            validCommand ? "true" : "false");
        Assert.True(result.ExitCode == 0, result.Output);
    }
 
    private static YamlMappingNode[] LoadSteps()
    {
        var steps = Assert.IsType<YamlSequenceNode>(LoadJob().Children[new YamlScalarNode("steps")]);
        return steps.Children.Select(Assert.IsType<YamlMappingNode>).ToArray();
    }
 
    private static YamlMappingNode LoadJob()
    {
        using var reader = File.OpenText(Path.Combine(RepoRoot.Path, ".github", "workflows", "deployment-test-command.yml"));
        var yaml = new YamlStream();
        yaml.Load(reader);
        var root = Assert.IsType<YamlMappingNode>(yaml.Documents[0].RootNode);
        var jobs = Assert.IsType<YamlMappingNode>(root.Children[new YamlScalarNode("jobs")]);
        return Assert.IsType<YamlMappingNode>(jobs.Children[new YamlScalarNode("deployment-test")]);
    }
 
    private static string Scalar(YamlMappingNode node, string key)
        => Assert.IsType<YamlScalarNode>(node.Children[new YamlScalarNode(key)]).Value!;
}