// Copyright 2026 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package convert import ( "fmt" "strings" "testing" actions_model "code.gitea.io/gitea/models/actions" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // buildWorkflowTestRepo creates a temporary git repository for testing GetActionWorkflow. // The default branch "main" has no workflow files; "feature" and "release-v1" each add their own workflow file. func buildWorkflowTestRepo(t *testing.T) string { t.Helper() ctx := t.Context() tmpDir := t.TempDir() _, _, err := gitcmd.NewCommand("init").WithDir(tmpDir).RunStdString(ctx) require.NoError(t, err) readme := "readme" featureWF := "on: [push]\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo test\n" releaseWF := "on: [push]\njobs:\n release:\n runs-on: ubuntu-latest\n steps:\n - run: echo release\n" // Build a git fast-import stream: // :4 = initial commit on main (README.md only) // :5 = feature branch commit (adds feature workflow) // :6 = release commit from :4 (adds release workflow, tagged release-v1, not on main) var sb strings.Builder fmt.Fprintf(&sb, "blob\nmark :1\ndata %d\n%s\n", len(readme), readme) fmt.Fprintf(&sb, "blob\nmark :2\ndata %d\n%s\n", len(featureWF), featureWF) fmt.Fprintf(&sb, "blob\nmark :3\ndata %d\n%s\n", len(releaseWF), releaseWF) fmt.Fprintf(&sb, "commit refs/heads/main\nmark :4\nauthor Test 1000000000 +0000\ncommitter Test 1000000000 +0000\ndata 14\ninitial commit\nM 100644 :1 README.md\n\n") fmt.Fprintf(&sb, "commit refs/heads/feature\nmark :5\nauthor Test 1000000001 +0000\ncommitter Test 1000000001 +0000\ndata 12\nadd workflow\nfrom :4\nM 100644 :2 .gitea/workflows/my-workflow.yml\n\n") fmt.Fprintf(&sb, "reset refs/pull/42/merge\nfrom :5\n\n") fmt.Fprintf(&sb, "commit refs/heads/main\nmark :6\nauthor Test 1000000002 +0000\ncommitter Test 1000000002 +0000\ndata 16\nrelease workflow\nfrom :4\nM 100644 :3 .gitea/workflows/my-workflow.yml\n\n") fmt.Fprintf(&sb, "reset refs/tags/release-v1\nfrom :6\n\n") fmt.Fprintf(&sb, "reset refs/heads/main\nfrom :4\n\n") fmt.Fprintf(&sb, "done\n") _, _, err = gitcmd.NewCommand("fast-import").WithDir(tmpDir).WithStdinBytes([]byte(sb.String())).RunStdString(ctx) require.NoError(t, err) return tmpDir } func TestGetActionWorkflow_FallbackRef(t *testing.T) { ctx := t.Context() repoDir := buildWorkflowTestRepo(t) gitRepo, err := git.OpenRepository(ctx, repoDir) require.NoError(t, err) defer gitRepo.Close() repo := &repo_model.Repository{ DefaultBranch: "main", OwnerName: "test-owner", Name: "test-repo", Units: []*repo_model.RepoUnit{ { Type: unit.TypeActions, Config: &repo_model.ActionsConfig{}, }, }, } t.Run("returns error when workflow only on non-default branch", func(t *testing.T) { _, err := GetActionWorkflow(ctx, gitRepo, repo, "my-workflow.yml") require.Error(t, err) assert.ErrorIs(t, err, util.ErrNotExist) }) t.Run("returns workflow when found via ref", func(t *testing.T) { wf, err := GetActionWorkflowByRef(ctx, gitRepo, repo, "my-workflow.yml", git.RefName("refs/heads/feature")) require.NoError(t, err) assert.Equal(t, "my-workflow.yml", wf.ID) }) t.Run("returns workflow when found via pull ref", func(t *testing.T) { wf, err := GetActionWorkflowByRef(ctx, gitRepo, repo, "my-workflow.yml", git.RefName("refs/pull/42/merge")) require.NoError(t, err) assert.Equal(t, "my-workflow.yml", wf.ID) assert.Contains(t, wf.HTMLURL, "/src/commit/") }) t.Run("returns workflow with tag link when found via tag ref", func(t *testing.T) { wf, err := GetActionWorkflowByRef(ctx, gitRepo, repo, "my-workflow.yml", git.RefName("refs/tags/release-v1")) require.NoError(t, err) assert.Equal(t, "my-workflow.yml", wf.ID) assert.Contains(t, wf.HTMLURL, "/src/tag/release-v1/") }) t.Run("returns error when workflow missing from ref", func(t *testing.T) { _, err := GetActionWorkflowByRef(ctx, gitRepo, repo, "nonexistent.yml", git.RefName("refs/heads/feature")) require.Error(t, err) assert.ErrorIs(t, err, util.ErrNotExist) }) } func TestToActionWorkflowRun_UsesTriggerEvent(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 803}) // Scheduled runs keep Event as the registration event (push) and use TriggerEvent as the real trigger. run.Event = "push" run.TriggerEvent = "schedule" apiRun, err := ToActionWorkflowRun(t.Context(), repo, run, nil) require.NoError(t, err) assert.Equal(t, "schedule", apiRun.Event) }