Skip to content

Commit

Permalink
feat()!: supporting workflowRunFile per repository (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamantal committed May 10, 2024
1 parent 9526320 commit 8589f08
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 78 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ ENVTEST ?= $(LOCALBIN)/setup-envtest

## Tool Versions
KUSTOMIZE_VERSION ?= v4.5.5
CONTROLLER_TOOLS_VERSION ?= v0.8.0
CONTROLLER_TOOLS_VERSION ?= v0.14.0

KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
.PHONY: kustomize
Expand Down
3 changes: 3 additions & 0 deletions api/v1alpha1/repository_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ type RepositorySpec struct {

// Whether the controller should sync all the pull requests belonging to the repository
SyncPullRequests SyncPullRequests `json:"syncPullRequests"`

// The names of the workflow files that should be checked when the status is updated
WorkflowFileNames []string `json:"workflowFileNames,omitempty"`
}

// RepositoryStatus defines the observed state of Repository
Expand Down
6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion charts/github-pr-controller/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ version: 0.1.0
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v0.1.4"
appVersion: "v0.1.5"
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: pullrequests.github.colossyan.com
spec:
group: github.colossyan.com
Expand All @@ -21,14 +20,19 @@ spec:
description: PullRequest is the Schema for the pullrequests API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
Expand Down Expand Up @@ -115,9 +119,3 @@ spec:
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: repositories.github.colossyan.com
spec:
group: github.colossyan.com
Expand All @@ -21,14 +20,19 @@ spec:
description: Repository is the Schema for the repositories API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
Expand All @@ -42,8 +46,9 @@ spec:
description: The owner of the repository
type: string
secretName:
description: The name of the Kubernetes secret containing the OAuth
token required for the controller to access private repositories
description: |-
The name of the Kubernetes secret containing the OAuth token required
for the controller to access private repositories
type: string
syncPullRequests:
description: Whether the controller should sync all the pull requests
Expand All @@ -61,6 +66,12 @@ spec:
required:
- enabled
type: object
workflowFileNames:
description: The names of the workflow files that should be checked
when the status is updated
items:
type: string
type: array
required:
- name
- owner
Expand All @@ -81,9 +92,3 @@ spec:
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
26 changes: 12 additions & 14 deletions config/crd/bases/github.colossyan.com_pullrequests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: pullrequests.github.colossyan.com
spec:
group: github.colossyan.com
Expand All @@ -21,14 +20,19 @@ spec:
description: PullRequest is the Schema for the pullrequests API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
Expand Down Expand Up @@ -115,9 +119,3 @@ spec:
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
37 changes: 21 additions & 16 deletions config/crd/bases/github.colossyan.com_repositories.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: repositories.github.colossyan.com
spec:
group: github.colossyan.com
Expand All @@ -21,14 +20,19 @@ spec:
description: Repository is the Schema for the repositories API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
Expand All @@ -42,8 +46,9 @@ spec:
description: The owner of the repository
type: string
secretName:
description: The name of the Kubernetes secret containing the OAuth
token required for the controller to access private repositories
description: |-
The name of the Kubernetes secret containing the OAuth token required
for the controller to access private repositories
type: string
syncPullRequests:
description: Whether the controller should sync all the pull requests
Expand All @@ -61,6 +66,12 @@ spec:
required:
- enabled
type: object
workflowFileNames:
description: The names of the workflow files that should be checked
when the status is updated
items:
type: string
type: array
required:
- name
- owner
Expand All @@ -81,9 +92,3 @@ spec:
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
1 change: 0 additions & 1 deletion config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: manager-role
rules:
- apiGroups:
Expand Down
2 changes: 1 addition & 1 deletion controllers/repository_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request)
}

logger.Info("syncing repository")
syncer := pkg.NewRepositorySyncer(logger, r.cache)
syncer := pkg.NewRepositorySyncer(logger, repository.Spec.WorkflowFileNames, r.cache)
repRequest := pkg.RepositorySyncInput{
Repository: repository,
Token: token,
Expand Down
49 changes: 36 additions & 13 deletions pkg/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"time"

"github.com/adamantal/github-pr-controller/api/v1alpha1"
githubv1alpha1 "github.com/adamantal/github-pr-controller/api/v1alpha1"
"github.com/go-logr/logr"
"github.com/google/go-github/v45/github"
Expand All @@ -13,8 +14,7 @@ import (
)

const (
pullRequestWorkflowFileName = "pull-request.yml"
maxPages = 20 // let's not rate-limit ourselves
maxPages = 20 // let's not rate-limit ourselves

day = 24 * time.Hour
week = 7 * day
Expand All @@ -23,8 +23,10 @@ const (

type RepositorySyncer struct {
logger logr.Logger
client *github.Client // lazy initialized
cache *RepositorySyncerCache // cache

workflowFileNames []string
client *github.Client // lazy initialized
cache *RepositorySyncerCache // cache
}

type RepositorySyncerCache struct {
Expand All @@ -42,10 +44,15 @@ type RepositorySyncOutput struct {
WorkflowRuns []*github.WorkflowRun
}

func NewRepositorySyncer(logger logr.Logger, cache *RepositorySyncerCache) RepositorySyncer {
func NewRepositorySyncer(
logger logr.Logger,
workflowFileNames []string,
cache *RepositorySyncerCache,
) RepositorySyncer {
return RepositorySyncer{
logger: logger,
cache: cache,
logger: logger,
workflowFileNames: workflowFileNames,
cache: cache,
}
}

Expand Down Expand Up @@ -142,6 +149,22 @@ func (rs *RepositorySyncer) sync(
}
rs.logger.V(1).Info("determined earliest timestamp", "ts", earliestTS)

for _, workflowFileName := range rs.workflowFileNames {
if err := rs.extractWorkflowRuns(ctx, client, req.Repository.Spec, workflowFileName, earliestTS); err != nil {
return nil, nil, errors.Wrap(err, "failed to extract ")
}
}

return prs, rs.cache.GetAllRuns(), nil
}

func (rs *RepositorySyncer) extractWorkflowRuns(
ctx context.Context,
client *github.Client,
repositorySpec v1alpha1.RepositorySpec,
pullRequestWorkflowFileName string,
earliestTS time.Time,
) error {
page := 1
for ; page < maxPages; page++ {
opts := github.ListWorkflowRunsOptions{
Expand All @@ -152,16 +175,16 @@ func (rs *RepositorySyncer) sync(
}

workflowRuns, _, err := client.Actions.ListWorkflowRunsByFileName(
ctx, req.Repository.Spec.Owner, req.Repository.Spec.Name, pullRequestWorkflowFileName, &opts)
ctx, repositorySpec.Owner, repositorySpec.Name, pullRequestWorkflowFileName, &opts)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to list workflows in repo")
return errors.Wrap(err, "failed to list workflows in repo")
}

if workflowRuns.WorkflowRuns == nil {
return nil, nil, errors.New("unexpected workflowruns returned from github API")
return errors.New("unexpected workflowruns returned from github API")
}
if len(workflowRuns.WorkflowRuns) == 0 {
return nil, nil, errors.New("empty workflowruns returned")
return errors.New("empty workflowruns returned")
}

cacheHit := rs.cache.SaveInCache(workflowRuns.WorkflowRuns)
Expand All @@ -170,9 +193,9 @@ func (rs *RepositorySyncer) sync(
break
}
}
rs.logger.V(1).Info("paginated workflow runs collected", "pages", page)
rs.logger.V(1).Info("paginated workflow runs collected", "workflowFileName", pullRequestWorkflowFileName, "pages", page)

return prs, rs.cache.GetAllRuns(), nil
return nil
}

func createGithubClient(ctx context.Context, token string) *github.Client {
Expand Down

0 comments on commit 8589f08

Please sign in to comment.