added terraform tests for the resource Reviewed-on: https://gitea.com/gitea/terraform-provider-gitea/pulls/72 Co-authored-by: Jörg Markert <joerg.markert@gmail.com> Co-committed-by: Jörg Markert <joerg.markert@gmail.com>
495 lines
18 KiB
Go
495 lines
18 KiB
Go
package gitea
|
|
|
|
import (
|
|
"log"
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
)
|
|
|
|
const (
|
|
repoBPUsername string = "username"
|
|
repoBPName string = "name"
|
|
repoBPRuleName string = "rule_name"
|
|
|
|
repoBPProtectedFilePatterns string = "protected_file_patterns"
|
|
repoBPUnprotectedFilePatterns string = "unprotected_file_patterns"
|
|
|
|
repoBPEnablePush string = "enable_push"
|
|
repoBPEnablePushWhitelist string = "enable_push_whitelist"
|
|
repoBPPushWhitelistUsers string = "push_whitelist_users"
|
|
repoBPPushWhitelistTeams string = "push_whitelist_teams"
|
|
repoBPPushWhitelistDeployKeys string = "push_whitelist_deploy_keys"
|
|
|
|
repoBPRequireSignedCommits string = "require_signed_commits"
|
|
|
|
repoBPRequiredApprovals string = "required_approvals"
|
|
repoBPEnableApprovalWhitelist string = "enable_approval_whitelist"
|
|
repoBPApprovalWhitelistUsers string = "approval_whitelist_users"
|
|
repoBPApprovalWhitelistTeams string = "approval_whitelist_teams"
|
|
repoBPDismissStaleApprovals string = "dismiss_stale_approvals"
|
|
// not implemented in go-gitea-sdk
|
|
// repoBPIgnoreStaleApprovals string = "ignore_stale_approvals"
|
|
|
|
repoBPEnableStatusCheck string = "enable_status_check"
|
|
repoBPStatusCheckPatterns string = "status_check_patterns"
|
|
|
|
repoBPEnableMergeWhitelist string = "enable_merge_whitelist"
|
|
repoBPMergeWhitelistUsers string = "merge_whitelist_users"
|
|
repoBPMergeWhitelistTeams string = "merge_whitelist_teams"
|
|
|
|
repoBPBlockMergeOnRejectedReviews string = "block_merge_on_rejected_reviews"
|
|
repoBPBlockMergeOnOfficialReviewRequests string = "block_merge_on_official_review_requests"
|
|
repoBPBlockMergeOnOutdatedBranch string = "block_merge_on_outdated_branch"
|
|
|
|
repoBPUpdatedAt string = "updated_at"
|
|
repoBPCreatedAt string = "created_at"
|
|
)
|
|
|
|
func resourceRepositoryBranchProtectionRead(d *schema.ResourceData, meta interface{}) (err error) {
|
|
client := meta.(*gitea.Client)
|
|
|
|
user := d.Get(repoBPUsername).(string)
|
|
repo := d.Get(repoBPName).(string)
|
|
rule_name := d.Get(repoBPRuleName).(string)
|
|
|
|
bp, resp, err := client.GetBranchProtection(user, repo, rule_name)
|
|
if err != nil {
|
|
if resp.StatusCode == 404 {
|
|
d.SetId("")
|
|
return
|
|
} else {
|
|
return err
|
|
}
|
|
}
|
|
|
|
err = setRepositoryBranchProtectionData(bp, user, repo, d)
|
|
return err
|
|
}
|
|
|
|
func generateWhitelist(d *schema.ResourceData, listname string) (enabled bool, users []string, teams []string) {
|
|
u := d.Get(listname + "_users")
|
|
users = make([]string, 0)
|
|
if u != nil {
|
|
for _, element := range u.([]interface{}) {
|
|
users = append(users, element.(string))
|
|
}
|
|
}
|
|
|
|
t := d.Get(listname + "_teams")
|
|
teams = make([]string, 0)
|
|
if u != nil {
|
|
for _, element := range t.([]interface{}) {
|
|
teams = append(teams, element.(string))
|
|
}
|
|
}
|
|
|
|
if c := len(users) + len(teams); c > 0 {
|
|
enabled = true
|
|
}
|
|
if listname == "push_whitelist" && d.Get(repoBPPushWhitelistDeployKeys).(bool) {
|
|
enabled = true
|
|
}
|
|
|
|
log.Println("enabled?:", enabled, listname)
|
|
return enabled, users, teams
|
|
}
|
|
|
|
func resourceRepositoryBranchProtectionCreate(d *schema.ResourceData, meta interface{}) (err error) {
|
|
client := meta.(*gitea.Client)
|
|
|
|
user := d.Get(repoBPUsername).(string)
|
|
repo := d.Get(repoBPName).(string)
|
|
|
|
enablePushWhitelist, pushWhitelistUsernames, pushWhitelistTeams := generateWhitelist(d, "push_whitelist")
|
|
enableMergeWhitelist, mergeWhitelistUsernames, mergeWhitelistTeams := generateWhitelist(d, "merge_whitelist")
|
|
enableApprovalsWhitelist, approvalsWhitelistUsernames, approvalsWhitelistTeams := generateWhitelist(d, "approval_whitelist")
|
|
|
|
statusCheckContexts := make([]string, 0)
|
|
for _, element := range d.Get(repoBPStatusCheckPatterns).([]interface{}) {
|
|
statusCheckContexts = append(statusCheckContexts, element.(string))
|
|
}
|
|
|
|
log.Println("create_ulist:", pushWhitelistUsernames)
|
|
|
|
enableStatusCheck := false
|
|
if len(statusCheckContexts) > 0 {
|
|
enableStatusCheck = true
|
|
}
|
|
|
|
bpOption := gitea.CreateBranchProtectionOption{
|
|
// BranchName is deprecated in gitea, but still required in go-gitea-sdk, therefore using RuleName
|
|
BranchName: d.Get(repoBPRuleName).(string),
|
|
RuleName: d.Get(repoBPRuleName).(string),
|
|
EnablePush: d.Get(repoBPEnablePush).(bool),
|
|
EnablePushWhitelist: enablePushWhitelist,
|
|
PushWhitelistUsernames: pushWhitelistUsernames,
|
|
PushWhitelistTeams: pushWhitelistTeams,
|
|
PushWhitelistDeployKeys: d.Get(repoBPPushWhitelistDeployKeys).(bool),
|
|
EnableMergeWhitelist: enableMergeWhitelist,
|
|
MergeWhitelistUsernames: mergeWhitelistUsernames,
|
|
MergeWhitelistTeams: mergeWhitelistTeams,
|
|
EnableStatusCheck: enableStatusCheck,
|
|
StatusCheckContexts: statusCheckContexts,
|
|
RequiredApprovals: int64(d.Get(repoBPRequiredApprovals).(int)),
|
|
EnableApprovalsWhitelist: enableApprovalsWhitelist,
|
|
ApprovalsWhitelistUsernames: approvalsWhitelistUsernames,
|
|
ApprovalsWhitelistTeams: approvalsWhitelistTeams,
|
|
BlockOnRejectedReviews: d.Get(repoBPBlockMergeOnRejectedReviews).(bool),
|
|
BlockOnOfficialReviewRequests: d.Get(repoBPBlockMergeOnOfficialReviewRequests).(bool),
|
|
BlockOnOutdatedBranch: d.Get(repoBPBlockMergeOnOutdatedBranch).(bool),
|
|
DismissStaleApprovals: d.Get(repoBPDismissStaleApprovals).(bool),
|
|
// IgnoreStaleApprovals: d.Get(repoBPIgnoreStaleApprovals).(bool),
|
|
RequireSignedCommits: d.Get(repoBPRequireSignedCommits).(bool),
|
|
ProtectedFilePatterns: d.Get(repoBPProtectedFilePatterns).(string),
|
|
UnprotectedFilePatterns: d.Get(repoBPUnprotectedFilePatterns).(string),
|
|
}
|
|
|
|
bp, _, err := client.CreateBranchProtection(user, repo, bpOption)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = setRepositoryBranchProtectionData(bp, user, repo, d)
|
|
return err
|
|
}
|
|
|
|
func resourceRepositoryBranchProtectionUpdate(d *schema.ResourceData, meta interface{}) (err error) {
|
|
client := meta.(*gitea.Client)
|
|
|
|
user := d.Get(repoBPUsername).(string)
|
|
repo := d.Get(repoBPName).(string)
|
|
rule_name := d.Id()
|
|
|
|
enablePushWhitelist, pushWhitelistUsernames, pushWhitelistTeams := generateWhitelist(d, "push_whitelist")
|
|
enableMergeWhitelist, mergeWhitelistUsernames, mergeWhitelistTeams := generateWhitelist(d, "merge_whitelist")
|
|
enableApprovalsWhitelist, approvalsWhitelistUsernames, approvalsWhitelistTeams := generateWhitelist(d, "approval_whitelist")
|
|
|
|
statusCheckContexts := make([]string, 0)
|
|
for _, element := range d.Get(repoBPStatusCheckPatterns).([]interface{}) {
|
|
statusCheckContexts = append(statusCheckContexts, element.(string))
|
|
}
|
|
|
|
enablePush := false
|
|
if enablePushWhitelist == true || d.Get(repoBPEnablePush).(bool) == true {
|
|
enablePush = true
|
|
}
|
|
pushWhitelistDeployKeys := d.Get(repoBPPushWhitelistDeployKeys).(bool)
|
|
enableStatusCheck := false
|
|
if len(statusCheckContexts) > 0 {
|
|
enableStatusCheck = true
|
|
}
|
|
requiredApprovals := int64(d.Get(repoBPRequiredApprovals).(int))
|
|
blockOnRejectedReviews := d.Get(repoBPBlockMergeOnRejectedReviews).(bool)
|
|
blockOnOfficialReviewRequests := d.Get(repoBPBlockMergeOnOfficialReviewRequests).(bool)
|
|
blockOnOutdatedBranch := d.Get(repoBPBlockMergeOnOutdatedBranch).(bool)
|
|
dismissStaleApprovals := d.Get(repoBPDismissStaleApprovals).(bool)
|
|
// ignoreStaleApprovals := d.Get(repoBPIgnoreStaleApprovals).(bool)
|
|
requireSignedCommits := d.Get(repoBPRequireSignedCommits).(bool)
|
|
protectedFilePatterns := d.Get(repoBPProtectedFilePatterns).(string)
|
|
unprotectedFilePatterns := d.Get(repoBPUnprotectedFilePatterns).(string)
|
|
|
|
bpOption := gitea.EditBranchProtectionOption{
|
|
EnablePush: &enablePush,
|
|
EnablePushWhitelist: &enablePushWhitelist,
|
|
PushWhitelistUsernames: pushWhitelistUsernames,
|
|
PushWhitelistTeams: pushWhitelistTeams,
|
|
PushWhitelistDeployKeys: &pushWhitelistDeployKeys,
|
|
EnableMergeWhitelist: &enableMergeWhitelist,
|
|
MergeWhitelistUsernames: mergeWhitelistUsernames,
|
|
MergeWhitelistTeams: mergeWhitelistTeams,
|
|
EnableStatusCheck: &enableStatusCheck,
|
|
StatusCheckContexts: statusCheckContexts,
|
|
RequiredApprovals: &requiredApprovals,
|
|
EnableApprovalsWhitelist: &enableApprovalsWhitelist,
|
|
ApprovalsWhitelistUsernames: approvalsWhitelistUsernames,
|
|
ApprovalsWhitelistTeams: approvalsWhitelistTeams,
|
|
BlockOnRejectedReviews: &blockOnRejectedReviews,
|
|
BlockOnOfficialReviewRequests: &blockOnOfficialReviewRequests,
|
|
BlockOnOutdatedBranch: &blockOnOutdatedBranch,
|
|
DismissStaleApprovals: &dismissStaleApprovals,
|
|
// IgnoreStaleApprovals: &ignoreStaleApprovals,
|
|
RequireSignedCommits: &requireSignedCommits,
|
|
ProtectedFilePatterns: &protectedFilePatterns,
|
|
UnprotectedFilePatterns: &unprotectedFilePatterns,
|
|
}
|
|
|
|
bp, _, err := client.EditBranchProtection(user, repo, rule_name, bpOption)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = setRepositoryBranchProtectionData(bp, user, repo, d)
|
|
return err
|
|
}
|
|
|
|
func resourceRepositoryBranchProtectionDelete(d *schema.ResourceData, meta interface{}) (err error) {
|
|
client := meta.(*gitea.Client)
|
|
|
|
user := d.Get(repoBPUsername).(string)
|
|
repo := d.Get(repoBPName).(string)
|
|
rule_name := d.Id()
|
|
|
|
_, err = client.DeleteBranchProtection(user, repo, rule_name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func setRepositoryBranchProtectionData(bp *gitea.BranchProtection, user string, repo string, d *schema.ResourceData) (err error) {
|
|
d.SetId(bp.RuleName)
|
|
d.Set(repoBPUsername, user)
|
|
d.Set(repoBPName, repo)
|
|
d.Set(repoBPProtectedFilePatterns, bp.ProtectedFilePatterns)
|
|
d.Set(repoBPUnprotectedFilePatterns, bp.UnprotectedFilePatterns)
|
|
d.Set(repoBPEnablePush, bp.EnablePush)
|
|
d.Set(repoBPEnablePushWhitelist, bp.EnablePushWhitelist)
|
|
d.Set(repoBPPushWhitelistUsers, bp.PushWhitelistUsernames)
|
|
d.Set(repoBPPushWhitelistTeams, bp.PushWhitelistTeams)
|
|
d.Set(repoBPPushWhitelistDeployKeys, bp.PushWhitelistDeployKeys)
|
|
d.Set(repoBPRequireSignedCommits, bp.RequireSignedCommits)
|
|
d.Set(repoBPRequiredApprovals, bp.RequiredApprovals)
|
|
d.Set(repoBPEnableApprovalWhitelist, bp.EnableApprovalsWhitelist)
|
|
d.Set(repoBPApprovalWhitelistUsers, bp.ApprovalsWhitelistUsernames)
|
|
d.Set(repoBPApprovalWhitelistTeams, bp.ApprovalsWhitelistTeams)
|
|
d.Set(repoBPDismissStaleApprovals, bp.DismissStaleApprovals)
|
|
// d.Set(repoBPIgnoreStaleApprovals, bp.IgnoreStaleApprovals)
|
|
d.Set(repoBPEnableStatusCheck, bp.EnableStatusCheck)
|
|
d.Set(repoBPStatusCheckPatterns, bp.StatusCheckContexts)
|
|
d.Set(repoBPEnableMergeWhitelist, bp.EnableMergeWhitelist)
|
|
d.Set(repoBPMergeWhitelistUsers, bp.MergeWhitelistUsernames)
|
|
d.Set(repoBPMergeWhitelistTeams, bp.MergeWhitelistTeams)
|
|
d.Set(repoBPBlockMergeOnRejectedReviews, bp.BlockOnRejectedReviews)
|
|
d.Set(repoBPBlockMergeOnOfficialReviewRequests, bp.BlockOnOfficialReviewRequests)
|
|
d.Set(repoBPBlockMergeOnOutdatedBranch, bp.BlockOnOutdatedBranch)
|
|
d.Set(repoBPUpdatedAt, bp.Updated)
|
|
d.Set(repoBPCreatedAt, bp.Created)
|
|
|
|
return err
|
|
}
|
|
|
|
func resourceGiteaRepositoryBranchProtection() *schema.Resource {
|
|
return &schema.Resource{
|
|
Read: resourceRepositoryBranchProtectionRead,
|
|
Create: resourceRepositoryBranchProtectionCreate,
|
|
Update: resourceRepositoryBranchProtectionUpdate,
|
|
Delete: resourceRepositoryBranchProtectionDelete,
|
|
// TODO: importer ?
|
|
Schema: map[string]*schema.Schema{
|
|
"username": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
Description: "User name or organization name",
|
|
},
|
|
"name": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
Description: "Repository name",
|
|
},
|
|
"rule_name": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
Description: "Protected Branch Name Pattern",
|
|
},
|
|
"protected_file_patterns": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: "",
|
|
Description: "Protected file patterns (separated using semicolon ';')",
|
|
},
|
|
"unprotected_file_patterns": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: "",
|
|
Description: "Unprotected file patterns (separated using semicolon ';')",
|
|
},
|
|
"enable_push": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: `Anyone with write access will be allowed to push to this branch
|
|
(but not force push), add a whitelist users or teams to limit
|
|
access.`,
|
|
},
|
|
"enable_push_whitelist": {
|
|
Type: schema.TypeBool,
|
|
Computed: true,
|
|
Description: "True if a push whitelist is used.",
|
|
},
|
|
"push_whitelist_users": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
RequiredWith: []string{"enable_push"},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: "Allowlisted users for pushing. Requires enable_push to be set to true.",
|
|
},
|
|
"push_whitelist_teams": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
RequiredWith: []string{"enable_push"},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: "Allowlisted teams for pushing. Requires enable_push to be set to true.",
|
|
},
|
|
"push_whitelist_deploy_keys": {
|
|
Type: schema.TypeBool,
|
|
RequiredWith: []string{"enable_push"},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: "Allow deploy keys with write access to push. Requires enable_push to be set to true.",
|
|
},
|
|
"require_signed_commits": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: "Reject pushes to this branch if they are unsigned or unverifiable.",
|
|
},
|
|
"required_approvals": {
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: 0,
|
|
Description: "Allow only to merge pull request with enough positive reviews.",
|
|
},
|
|
"enable_approval_whitelist": {
|
|
Type: schema.TypeBool,
|
|
Computed: true,
|
|
Description: "True if a approval whitelist is used.",
|
|
},
|
|
"approval_whitelist_users": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: `Only reviews from allowlisted users will count to the required
|
|
approvals. Without approval allowlist, reviews from anyone with
|
|
write access count to the required approvals.`,
|
|
},
|
|
"approval_whitelist_teams": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: `Only reviews from allowlisted teams will count to the required
|
|
approvals. Without approval allowlist, reviews from anyone with
|
|
write access count to the required approvals.`,
|
|
},
|
|
"dismiss_stale_approvals": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: `When new commits that change the content of the pull request
|
|
are pushed to the branch, old approvals will be dismissed.`,
|
|
},
|
|
//
|
|
// not implemented in go-gitea-sdk
|
|
//
|
|
// "ignore_stale_approvals": {
|
|
// Type: schema.TypeBool,
|
|
// Optional true,
|
|
// ForceNew: false,
|
|
// Default: false,
|
|
// Description: `Do not count approvals that were made on older commits (stale
|
|
// reviews) towards how many approvals the PR has. Irrelevant if
|
|
// stale reviews are already dismissed.`,
|
|
// },
|
|
"enable_status_check": {
|
|
Type: schema.TypeBool,
|
|
Computed: true,
|
|
Description: `Require status checks to pass before merging. When enabled,
|
|
commits must first be pushed to another branch, then merged
|
|
or pushed directly to a branch that matches this rule after
|
|
status checks have passed. If no contexts are matched, the
|
|
last commit must be successful regardless of context`,
|
|
},
|
|
"status_check_patterns": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: `Enter patterns to specify which status checks must pass before
|
|
branches can be merged into a branch that matches this rule.
|
|
Each line specifies a pattern. Patterns cannot be empty.`,
|
|
},
|
|
"enable_merge_whitelist": {
|
|
Type: schema.TypeBool,
|
|
Computed: true,
|
|
Description: "True if a merge whitelist is used.",
|
|
},
|
|
"merge_whitelist_users": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: "Allow only allowlisted users to merge pull requests into this branch.",
|
|
},
|
|
"merge_whitelist_teams": {
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Description: "Allow only allowlisted teams to merge pull requests into this branch.",
|
|
},
|
|
"block_merge_on_rejected_reviews": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: `Merging will not be possible when changes are
|
|
requested by official reviewers, even if there are enough
|
|
approvals.`,
|
|
},
|
|
"block_merge_on_official_review_requests": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: `Merging will not be possible when it has official
|
|
review requests, even if there are enough approvals.`,
|
|
},
|
|
"block_merge_on_outdated_branch": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Default: false,
|
|
Description: "Merging will not be possible when head branch is behind base branch.",
|
|
},
|
|
"updated_at": {
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
Description: "Webhook creation timestamp",
|
|
},
|
|
"created_at": {
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
Description: "Webhook creation timestamp",
|
|
},
|
|
},
|
|
Description: "This resource allows you to create and manage branch protections for repositories.",
|
|
}
|
|
}
|