enhance(actions): set ref_protected in context (#38852)

## Problem

The github.ref_protected Actions context value was hard-coded to false,
even when Gitea has a matching protected-branch or protected-tag rule.

That prevents policy-driven deployment workflows from relying on Gitea
as the source of truth. A deployment runner or external identity
provider may require a protected ref before releasing credentials. The
workaround is an exact-ref allowlist outside Gitea, which duplicates
repository protection policy and can drift when rules change.

## Solution

Resolve configured protection rules for branch and tag refs.
Non-branch/tag refs remain false; lookup failures are logged and
conservatively return false.

This changes the Actions context only; it does not add Actions OIDC
issuance.

---------

Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
Vitalii Tverdokhlib
2026-08-10 22:55:29 +02:00
committed by GitHub
co-authored by Giteabot
parent a8fe401613
commit 52d0e18dac
3 changed files with 85 additions and 1 deletions
+42
View File
@@ -10,6 +10,7 @@ import (
act_model "gitea.dev/actionslib/pkg/model"
actions_model "gitea.dev/models/actions"
"gitea.dev/models/db"
git_model "gitea.dev/models/git"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
@@ -355,6 +356,47 @@ func TestGenerateGiteaContextPullRequestTarget(t *testing.T) {
assert.Equal(t, "main", giteaCtx["ref_name"])
}
func TestGenerateGiteaContextRefProtected(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
require.NoError(t, git_model.UpdateProtectBranch(t.Context(), repo, &git_model.ProtectedBranch{
RepoID: repo.ID,
RuleName: "master",
}, git_model.WhitelistOptions{}))
require.NoError(t, git_model.InsertProtectedTag(t.Context(), &git_model.ProtectedTag{
RepoID: repo.ID,
NamePattern: "v*",
}))
gitCtx := GenerateGiteaContext(t.Context(), &actions_model.ActionRun{
RepoID: repo.ID,
Repo: repo,
TriggerUser: &user_model.User{Name: "test-user"},
Ref: "refs/heads/master",
}, nil, nil)
assert.Equal(t, true, gitCtx["ref_protected"])
tagCtx := GenerateGiteaContext(t.Context(), &actions_model.ActionRun{
RepoID: repo.ID,
Repo: repo,
TriggerUser: &user_model.User{Name: "test-user"},
Ref: "refs/tags/v1.0.0",
}, nil, nil)
assert.Equal(t, true, tagCtx["ref_protected"])
unprotectedTagCtx := GenerateGiteaContext(t.Context(), &actions_model.ActionRun{
RepoID: repo.ID,
Repo: repo,
TriggerUser: &user_model.User{Name: "test-user"},
Ref: "refs/tags/other",
}, nil, nil)
assert.Equal(t, false, unprotectedTagCtx["ref_protected"])
}
// TestGenerateGiteaContext_NilAttempt verifies that, with no explicit attempt,
// use GetLatestAttempt to load the latest attempt and resolve attempt-related context variables.
func TestGenerateGiteaContext_NilAttempt(t *testing.T) {