3.6 KiB · text History b868907
defmodule GitGud.Workflows.RefEventDispatchTest do
  @moduledoc """
  `on: create` and `on: delete`: a branch or tag appearing or going away.
  """
  use GitGud.DataCase, async: false

  alias GitGud.Repositories.Repository
  alias GitGud.Workflows.WorkflowRun

  import GitGud.ForgeFixtures
  import GitGud.WorkflowGitHelpers

  @moduletag :capture_log

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

  @refs ".forgejo/workflows/refs.yml"
  @push ".forgejo/workflows/push.yml"

  setup do
    {user, repo} = repository_fixture()
    {:ok, repo: repo, user: user}
  end

  defp runs(%Repository{id: rid}, trigger) do
    from(r in WorkflowRun,
      where: r.repository_id == ^rid and r.trigger == ^trigger,
      order_by: r.id
    )
    |> Repo.all()
  end

  test "creating a branch fires create and push; filters don't apply", %{
    repo: repo,
    user: user
  } do
    files = %{
      @refs => workflow("refs", "  create:\n    branches: [nope]\n  delete:\n"),
      @push => workflow("push", "  push:\n")
    }

    head = commit!(repo, files, [])
    push_ref!(repo, "refs/heads/feature", nil, head, user.id)

    assert [create] = runs(repo, "create")
    assert create.workflow_path == @refs
    assert create.head_ref == "refs/heads/feature"
    assert create.head_sha == sha!(head)
    assert create.triggered_by_id == user.id
    assert create.event_payload["ref"] == "feature"
    assert create.event_payload["ref_type"] == "branch"

    assert [push] = runs(repo, "push")
    assert push.workflow_path == @push

    # Moving it again isn't a create.
    next = commit!(repo, Map.put(files, "a", "a\n"), [head])
    push_ref!(repo, "refs/heads/feature", head, next, user.id)
    assert [_create] = runs(repo, "create")
  end

  test "a tag is a create with ref_type tag", %{repo: repo} do
    head = commit!(repo, %{@refs => workflow("refs", "  create:\n")}, [])
    push_ref!(repo, "refs/tags/v1", nil, head)

    assert [run] = runs(repo, "create")
    assert run.event_payload["ref_type"] == "tag"
    assert run.event_payload["ref"] == "v1"
  end

  test "deleting a branch runs the default branch's delete workflows", %{repo: repo} do
    main = commit!(repo, %{@refs => workflow("refs-main", "  delete:\n")}, [])
    push_ref!(repo, "refs/heads/main", nil, main)

    # The branch's own file doesn't say `delete:`, and it's gone anyway.
    feature = commit!(repo, %{@push => workflow("push", "  push:\n")}, [main])
    push_ref!(repo, "refs/heads/feature", nil, feature)
    push_ref!(repo, "refs/heads/feature", feature, nil)

    assert [run] = runs(repo, "delete")
    assert run.workflow_name == "refs-main"
    assert run.head_ref == "refs/heads/main"
    assert run.head_sha == sha!(main)
    assert run.event_payload["ref"] == "feature"
    assert run.event_payload["ref_type"] == "branch"
  end

  test "a workflow with only push: fires on neither", %{repo: repo} do
    main = commit!(repo, %{@push => workflow("push", "  push:\n    branches: [main]\n")}, [])
    push_ref!(repo, "refs/heads/main", nil, main)
    push_ref!(repo, "refs/heads/feature", nil, main)
    push_ref!(repo, "refs/heads/feature", main, nil)

    assert runs(repo, "create") == []
    assert runs(repo, "delete") == []
  end

  test "deleting the default branch itself runs nothing", %{repo: repo} do
    main = commit!(repo, %{@refs => workflow("refs", "  delete:\n")}, [])
    push_ref!(repo, "refs/heads/main", nil, main)
    push_ref!(repo, "refs/heads/main", main, nil)

    assert runs(repo, "delete") == []
  end
end