2.8 KiB · text History b868907
defmodule GitGud.Workflows.DispatchLookupTest do
  @moduledoc """
  Which workflow `dispatch_manual/4` runs for a name: the path, the file
  name, the file name without its extension, or the `name:` — in that
  order, the first that matches anything deciding, and two matches there
  refused rather than guessed between.
  """
  use GitGud.DataCase, async: true

  alias GitGud.Workflows
  alias GitGud.Workflows.WorkflowRun

  import GitGud.ForgeFixtures
  import GitGud.WorkflowGitHelpers

  defp workflow(name) do
    """
    name: #{name}
    on: { workflow_dispatch: }
    jobs:
      only:
        runs-on: self-hosted
        steps:
          - run: echo #{name}
    """
  end

  setup do
    {_user, repo} = repository_fixture()

    head =
      commit!(
        repo,
        %{
          ".forgejo/workflows/audit.yml" => workflow("Nightly audit"),
          ".forgejo/workflows/release.yaml" => workflow("ship"),
          ".forgejo/workflows/build.yml" => workflow("build"),
          ".forgejo/workflows/build-arm.yml" => workflow("Build"),
          # Named like another workflow's file stem: the stem match wins.
          ".forgejo/workflows/lint.yml" => workflow("audit")
        },
        []
      )

    git!(repo.disk_path, ["update-ref", "refs/heads/main", head])
    {:ok, repo: repo}
  end

  defp ran(repo, name) do
    case Workflows.dispatch_manual(repo, name, "main") do
      {:ok, %WorkflowRun{workflow_path: path}} -> path
      other -> other
    end
  end

  test "by path and by file name, as before", %{repo: repo} do
    assert ran(repo, ".forgejo/workflows/audit.yml") == ".forgejo/workflows/audit.yml"
    assert ran(repo, "audit.yml") == ".forgejo/workflows/audit.yml"
  end

  test "by the file name without .yml or .yaml", %{repo: repo} do
    assert ran(repo, "audit") == ".forgejo/workflows/audit.yml"
    assert ran(repo, "release") == ".forgejo/workflows/release.yaml"
  end

  test "by name:, in any case", %{repo: repo} do
    assert ran(repo, "Nightly audit") == ".forgejo/workflows/audit.yml"
    assert ran(repo, "SHIP") == ".forgejo/workflows/release.yaml"
  end

  test "a more specific match wins over a name: elsewhere", %{repo: repo} do
    # lint.yml is named "audit", but audit.yml's stem matches first.
    assert ran(repo, "audit") == ".forgejo/workflows/audit.yml"
  end

  test "two at the same step are refused, naming both", %{repo: repo} do
    # "build" is build.yml's stem, so that wins; "BUILD" is no stem and
    # matches both name:s.
    assert ran(repo, "build") == ".forgejo/workflows/build.yml"

    assert ran(repo, "BUILD") ==
             {:error,
              {:ambiguous_workflow,
               [".forgejo/workflows/build-arm.yml", ".forgejo/workflows/build.yml"]}}
  end

  test "nothing matching is still unknown", %{repo: repo} do
    assert ran(repo, "deploy") == {:error, :unknown_workflow}
  end
end