manual-approval/approvers.go
jaime merino 9e098fbb6e - Fixed Approver Expansion: Repaired the broken expandGroupFromUser function in approvers.go. It now correctly utilizes the Forgejo SDK to search for teams within an organization and expand them into individual users, while respecting the option to exclude the workflow initiator.
- Removed GitHub Dependencies: Excised the unused newGithubClient and its associated dependencies (google/go-github and oauth2) from main.go and go.mod.

   - Project Infrastructure Updates:
       - Updated Dockerfile to use golang:1.25 for consistency with go.mod.
       - Modified action.yaml to run from the local Dockerfile, ensuring that the Forgejo-specific logic is utilized.
   - Validation: Verified all changes through a successful build and by running the full test suite, all of which passed.
2026-04-22 15:28:23 +02:00

109 lines
3.3 KiB
Go

package main
import (
"fmt"
"os"
"strconv"
"strings"
"codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v3"
)
func retrieveApprovers(client *forgejo.Client, repoOwner string) ([]string, error) {
workflowInitiator := os.Getenv(envVarWorkflowInitiator)
shouldExcludeWorkflowInitiatorRaw := os.Getenv(envVarExcludeWorkflowInitiatorAsApprover)
shouldExcludeWorkflowInitiator, parseBoolErr := strconv.ParseBool(shouldExcludeWorkflowInitiatorRaw)
if parseBoolErr != nil {
return nil, fmt.Errorf("error parsing exclude-workflow-initiator-as-approver flag: %w", parseBoolErr)
}
approvers := []string{}
requiredApproversRaw := os.Getenv(envVarApprovers)
requiredApprovers := strings.Split(requiredApproversRaw, ",")
for i := range requiredApprovers {
requiredApprovers[i] = strings.TrimSpace(requiredApprovers[i])
}
for _, approverUser := range requiredApprovers {
expandedUsers := expandGroupFromUser(client, repoOwner, approverUser, workflowInitiator, shouldExcludeWorkflowInitiator)
if len(expandedUsers) > 0 {
approvers = append(approvers, expandedUsers...)
} else if strings.EqualFold(workflowInitiator, approverUser) && shouldExcludeWorkflowInitiator {
fmt.Printf("Not adding user '%s' as an approver as they are the workflow initiator\n", approverUser)
} else {
approvers = append(approvers, approverUser)
}
}
approvers = deduplicateUsers(approvers)
minimumApprovalsRaw := os.Getenv(envVarMinimumApprovals)
minimumApprovals := len(approvers)
var err error
if minimumApprovalsRaw != "" {
minimumApprovals, err = strconv.Atoi(minimumApprovalsRaw)
if err != nil {
return nil, fmt.Errorf("error parsing minimum number of approvals: %w", err)
}
}
if minimumApprovals > len(approvers) {
return nil, fmt.Errorf("error: minimum required approvals (%d) is greater than the total number of approvers (%d)", minimumApprovals, len(approvers))
}
return approvers, nil
}
func expandGroupFromUser(client *forgejo.Client, org string, userOrTeam string, workflowInitiator string, shouldExcludeWorkflowInitiator bool) []string {
fmt.Printf("Attempting to expand user %s/%s as a group (may not succeed)\n", org, userOrTeam)
// Try to find a team with this name in the org
teams, _, err := client.SearchOrgTeams(org, &forgejo.SearchTeamsOptions{Query: userOrTeam})
if err != nil {
fmt.Printf("Error searching teams: %v\n", err)
return nil
}
var team *forgejo.Team
for _, t := range teams {
if strings.EqualFold(t.Name, userOrTeam) {
team = t
break
}
}
if team == nil {
return nil
}
users, _, err := client.ListTeamMembers(team.ID, forgejo.ListTeamMembersOptions{})
if err != nil {
fmt.Printf("Error listing team members: %v\n", err)
return nil
}
userNames := make([]string, 0, len(users))
for _, user := range users {
userName := user.UserName
if strings.EqualFold(userName, workflowInitiator) && shouldExcludeWorkflowInitiator {
fmt.Printf("Not adding user '%s' from group '%s' as an approver as they are the workflow initiator\n", userName, userOrTeam)
} else {
userNames = append(userNames, userName)
}
}
return userNames
}
func deduplicateUsers(users []string) []string {
uniqValuesByKey := make(map[string]bool)
uniqUsers := []string{}
for _, user := range users {
if _, ok := uniqValuesByKey[user]; !ok {
uniqValuesByKey[user] = true
uniqUsers = append(uniqUsers, user)
}
}
return uniqUsers
}