1
1
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-05 12:50:59 +02:00
Files
gitea/services/convert/action_test.go
Giteabot fc9dfe0e56 fix: use TriggerEvent instead of Event in workflow runs API response for scheduled runs (#37288) (#37360)
Backport #37288 by @KalashThakare

## Summary

Fixes #37252

The `/api/v1/repos/{owner}/{repo}/actions/runs` endpoint was returning
`event: "push"` for workflow runs triggered by `schedule:` (cron),
instead
of `event: "schedule"`.

## Root Cause

`ActionRun` has two separate fields:
- `Event` — the workflow registration event (e.g. `push`, set when the
workflow file was first pushed)
- `TriggerEvent` — the actual event that triggered the run (e.g.
`schedule`)

`ToActionWorkflowRun` in `services/convert/action.go` was serializing
`run.Event` into the API response instead of `run.TriggerEvent`, causing
scheduled runs to be indistinguishable from push events via the API.

This was already asymmetric — the tasks/jobs API correctly used
`TriggerEvent`.

## Fix

Changed `ToActionWorkflowRun` to use `run.TriggerEvent` for the `event`
field in the API response, consistent with how the jobs API works.

## Before

`event: "push"` returned for all scheduled runs:

<img width="1112" height="191" alt="Screenshot 2026-04-19 115642"
src="https://github.com/user-attachments/assets/c0a169f5-bbd9-4f5d-9474-e4c3795110e4"
/>

## After

`event: "schedule"` correctly returned for scheduled runs:

<img width="890" height="166" alt="Screenshot 2026-04-19 121723"
src="https://github.com/user-attachments/assets/860e99ac-0935-4a43-86a1-7b60f8113480"
/>


## Testing

- Added unit test `TestToActionWorkflowRun_UsesTriggerEvent` in
  `services/convert/action_test.go` that explicitly verifies the API
  returns `TriggerEvent` and not `Event` for a scheduled run.
- Manually verified via the API against a live Gitea instance with a
  `cron: "* * * * *"` workflow.

Co-authored-by: Kalash Thakare ☯︎ <kalashthakare898@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
2026-04-22 18:39:10 +02:00

127 lines
5.0 KiB
Go

// 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 <test@gitea.com> 1000000000 +0000\ncommitter Test <test@gitea.com> 1000000000 +0000\ndata 14\ninitial commit\nM 100644 :1 README.md\n\n")
fmt.Fprintf(&sb, "commit refs/heads/feature\nmark :5\nauthor Test <test@gitea.com> 1000000001 +0000\ncommitter Test <test@gitea.com> 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 <test@gitea.com> 1000000002 +0000\ncommitter Test <test@gitea.com> 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)
require.NoError(t, err)
assert.Equal(t, "schedule", apiRun.Event)
}