mirror of
https://github.com/go-gitea/gitea.git
synced 2026-03-27 15:39:17 +01:00
test for github supported scopes with test to ensure all of them work and don't panic fixes: https://github.com/go-gitea/gitea/issues/36967
227 lines
6.8 KiB
Go
227 lines
6.8 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package actions
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"code.gitea.io/gitea/models/perm"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
"code.gitea.io/gitea/models/unit"
|
|
"code.gitea.io/gitea/modules/actions/jobparser"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.yaml.in/yaml/v4"
|
|
)
|
|
|
|
func TestParseRawPermissions_ReadAll(t *testing.T) {
|
|
var rawPerms yaml.Node
|
|
err := yaml.Unmarshal([]byte(`read-all`), &rawPerms)
|
|
assert.NoError(t, err)
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
require.NotNil(t, result)
|
|
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeCode])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeIssues])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypePullRequests])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypePackages])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeActions])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeWiki])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeProjects])
|
|
}
|
|
|
|
// TestParseRawPermissions_GithubScopes verifies that all scopes that github supports are accounted for
|
|
func TestParseRawPermissions_GithubScopes(t *testing.T) {
|
|
var rawPerms yaml.Node
|
|
// Taken and stripped down from:
|
|
// https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#defining-access-for-the-github_token-scopes
|
|
yamlContent := `
|
|
actions: read
|
|
artifact-metadata: read
|
|
attestations: read
|
|
checks: read
|
|
contents: read
|
|
deployments: read
|
|
id-token: write
|
|
issues: read
|
|
models: read
|
|
discussions: read
|
|
packages: read
|
|
pages: read
|
|
pull-requests: read
|
|
security-events: read
|
|
statuses: read`
|
|
err := yaml.Unmarshal([]byte(yamlContent), &rawPerms)
|
|
require.NoError(t, err)
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
require.NotNil(t, result)
|
|
|
|
// No asserts for permissions set on purpose
|
|
}
|
|
|
|
func TestParseRawPermissions_WriteAll(t *testing.T) {
|
|
var rawPerms yaml.Node
|
|
err := yaml.Unmarshal([]byte(`write-all`), &rawPerms)
|
|
assert.NoError(t, err)
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
require.NotNil(t, result)
|
|
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeCode])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeIssues])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypePullRequests])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypePackages])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeActions])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeWiki])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeProjects])
|
|
}
|
|
|
|
func TestParseRawPermissions_IndividualScopes(t *testing.T) {
|
|
yamlContent := `
|
|
contents: write
|
|
issues: read
|
|
pull-requests: none
|
|
packages: write
|
|
actions: read
|
|
wiki: write
|
|
projects: none
|
|
`
|
|
var rawPerms yaml.Node
|
|
err := yaml.Unmarshal([]byte(yamlContent), &rawPerms)
|
|
assert.NoError(t, err)
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
require.NotNil(t, result)
|
|
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeCode])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeIssues])
|
|
assert.Equal(t, perm.AccessModeNone, result.UnitAccessModes[unit.TypePullRequests])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypePackages])
|
|
assert.Equal(t, perm.AccessModeRead, result.UnitAccessModes[unit.TypeActions])
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeWiki])
|
|
assert.Equal(t, perm.AccessModeNone, result.UnitAccessModes[unit.TypeProjects])
|
|
}
|
|
|
|
func TestParseRawPermissions_Priority(t *testing.T) {
|
|
t.Run("granular-wins-over-contents", func(t *testing.T) {
|
|
yamlContent := `
|
|
contents: read
|
|
code: write
|
|
releases: none
|
|
`
|
|
var rawPerms yaml.Node
|
|
err := yaml.Unmarshal([]byte(yamlContent), &rawPerms)
|
|
assert.NoError(t, err)
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
require.NotNil(t, result)
|
|
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeCode])
|
|
assert.Equal(t, perm.AccessModeNone, result.UnitAccessModes[unit.TypeReleases])
|
|
})
|
|
|
|
t.Run("contents-applied-first", func(t *testing.T) {
|
|
yamlContent := `
|
|
code: none
|
|
releases: write
|
|
contents: read
|
|
`
|
|
var rawPerms yaml.Node
|
|
err := yaml.Unmarshal([]byte(yamlContent), &rawPerms)
|
|
assert.NoError(t, err)
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
require.NotNil(t, result)
|
|
|
|
// code: none should win over contents: read
|
|
assert.Equal(t, perm.AccessModeNone, result.UnitAccessModes[unit.TypeCode])
|
|
// releases: write should win over contents: read
|
|
assert.Equal(t, perm.AccessModeWrite, result.UnitAccessModes[unit.TypeReleases])
|
|
})
|
|
}
|
|
|
|
func TestParseRawPermissions_EmptyNode(t *testing.T) {
|
|
var rawPerms yaml.Node
|
|
// Empty node
|
|
|
|
result := parseRawPermissionsExplicit(&rawPerms)
|
|
|
|
// Should return nil for non-explicit
|
|
assert.Nil(t, result)
|
|
}
|
|
|
|
func TestParseRawPermissions_NilNode(t *testing.T) {
|
|
result := parseRawPermissionsExplicit(nil)
|
|
|
|
// Should return nil
|
|
assert.Nil(t, result)
|
|
}
|
|
|
|
func TestParseAccessMode(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected perm.AccessMode
|
|
}{
|
|
{"write", perm.AccessModeWrite},
|
|
{"read", perm.AccessModeRead},
|
|
{"none", perm.AccessModeNone},
|
|
{"", perm.AccessModeNone},
|
|
{"invalid", perm.AccessModeNone},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.input, func(t *testing.T) {
|
|
result := parseAccessMode(tt.input)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractJobPermissionsFromWorkflow(t *testing.T) {
|
|
workflowYAML := `
|
|
name: Test Permissions
|
|
on: workflow_dispatch
|
|
permissions: read-all
|
|
|
|
jobs:
|
|
job-read-only:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- run: echo "Full read-only"
|
|
|
|
job-none-perms:
|
|
permissions: none
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- run: echo "Full read-only"
|
|
|
|
job-override:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- run: echo "Override to write"
|
|
`
|
|
|
|
expectedPerms := map[string]*repo_model.ActionsTokenPermissions{}
|
|
expectedPerms["job-read-only"] = new(repo_model.MakeActionsTokenPermissions(perm.AccessModeRead))
|
|
expectedPerms["job-none-perms"] = new(repo_model.MakeActionsTokenPermissions(perm.AccessModeNone))
|
|
expectedPerms["job-override"] = new(repo_model.MakeActionsTokenPermissions(perm.AccessModeNone))
|
|
expectedPerms["job-override"].UnitAccessModes[unit.TypeCode] = perm.AccessModeWrite
|
|
expectedPerms["job-override"].UnitAccessModes[unit.TypeReleases] = perm.AccessModeWrite
|
|
|
|
singleWorkflows, err := jobparser.Parse([]byte(workflowYAML))
|
|
require.NoError(t, err)
|
|
for _, flow := range singleWorkflows {
|
|
jobID, jobDef := flow.Job()
|
|
require.NotNil(t, jobDef)
|
|
t.Run(jobID, func(t *testing.T) {
|
|
assert.Equal(t, expectedPerms[jobID], ExtractJobPermissionsFromWorkflow(flow, jobDef))
|
|
})
|
|
}
|
|
}
|