Skip to content

Commit 8563f07

Browse files
committed
Add Git information in Function status
1 parent e3f22ec commit 8563f07

7 files changed

Lines changed: 115 additions & 4 deletions

File tree

api/v1alpha1/function_types.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ type FunctionStatus struct {
7777
Runtime string `json:"runtime"`
7878

7979
Conditions []metav1.Condition `json:"conditions,omitempty"`
80+
81+
Git FunctionStatusGit `json:"git,omitempty"`
82+
}
83+
84+
type FunctionStatusGit struct {
85+
ResolvedBranch string `json:"resolvedBranch,omitempty"`
86+
ObservedCommit string `json:"observedCommit,omitempty"`
87+
LastChecked metav1.Time `json:"lastChecked,omitempty"`
8088
}
8189

8290
// +kubebuilder:object:root=true

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/functions.dev_functions.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ spec:
165165
- type
166166
type: object
167167
type: array
168+
git:
169+
properties:
170+
lastChecked:
171+
format: date-time
172+
type: string
173+
observedCommit:
174+
type: string
175+
resolvedBranch:
176+
type: string
177+
type: object
168178
name:
169179
type: string
170180
runtime:

internal/controller/function_controller.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ func (r *FunctionReconciler) reconcile(ctx context.Context, function *v1alpha1.F
121121
}
122122
defer repo.Cleanup()
123123

124+
r.updateFunctionStatusGit(function, repo)
125+
124126
if err := r.ensureDeployment(ctx, function, repo, metadata); err != nil {
125127
return fmt.Errorf("deploying function failed: %w", err)
126128
}
@@ -442,3 +444,10 @@ func (r *FunctionReconciler) isMiddlewareLatest(ctx context.Context, metadata *f
442444

443445
return latestMiddleware == functionMiddleware, nil
444446
}
447+
448+
// updateFunctionStatusGit updates the functions status with the Git information
449+
func (r *FunctionReconciler) updateFunctionStatusGit(function *v1alpha1.Function, repo *git.Repository) {
450+
function.Status.Git.ResolvedBranch = repo.Branch
451+
function.Status.Git.ObservedCommit = repo.Commit
452+
function.Status.Git.LastChecked = metav1.Now()
453+
}

internal/controller/function_controller_test.go

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ var _ = Describe("Function Controller", func() {
7575
type reconcileTestCase struct {
7676
spec functionsdevv1alpha1.FunctionSpec
7777
configureMocks func(*funccli.MockManager, *git.MockManager)
78+
statusChecks func(*functionsdevv1alpha1.FunctionStatus)
7879
}
7980

8081
DescribeTable("should successfully reconcile the resource",
@@ -101,6 +102,14 @@ var _ = Describe("Function Controller", func() {
101102
NamespacedName: typeNamespacedName,
102103
})
103104
Expect(err).NotTo(HaveOccurred())
105+
106+
if tc.statusChecks != nil {
107+
f := &functionsdevv1alpha1.Function{}
108+
err := k8sClient.Get(ctx, typeNamespacedName, f)
109+
Expect(err).NotTo(HaveOccurred())
110+
111+
tc.statusChecks(&f.Status)
112+
}
104113
},
105114
Entry("should deploy when middleware update required", reconcileTestCase{
106115
spec: defaultSpec,
@@ -149,6 +158,30 @@ var _ = Describe("Function Controller", func() {
149158
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
150159
},
151160
}),
161+
162+
Entry("should contain the git information in the status", reconcileTestCase{
163+
spec: functionsdevv1alpha1.FunctionSpec{
164+
Repository: functionsdevv1alpha1.FunctionSpecRepository{
165+
URL: "https://github.com/foo/bar",
166+
Branch: "my-branch",
167+
},
168+
},
169+
configureMocks: func(funcMock *funccli.MockManager, gitMock *git.MockManager) {
170+
funcMock.EXPECT().Describe(mock.Anything, functionName, resourceNamespace).Return(functions.Instance{
171+
Middleware: functions.Middleware{
172+
Version: "v1.0.0",
173+
},
174+
}, nil)
175+
funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v1.0.0", nil)
176+
funcMock.EXPECT().GetMiddlewareVersion(mock.Anything, functionName, resourceNamespace).Return("v1.0.0", nil)
177+
178+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "my-branch", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}, WithRepoOptionBranch("my-branch"), WithRepoOptionCommit("foobar")), nil)
179+
},
180+
statusChecks: func(status *functionsdevv1alpha1.FunctionStatus) {
181+
Expect(status.Git.ResolvedBranch).Should(Equal("my-branch"))
182+
Expect(status.Git.ObservedCommit).Should(Equal("foobar"))
183+
},
184+
}),
152185
)
153186
})
154187
})
@@ -165,7 +198,9 @@ func createFunctionResource(name, namespace string, spec functionsdevv1alpha1.Fu
165198
return k8sClient.Create(ctx, &resource)
166199
}
167200

168-
func createTmpGitRepo(function functions.Function) *git.Repository {
201+
type RepoOption func(*git.Repository)
202+
203+
func createTmpGitRepo(function functions.Function, repoOptions ...RepoOption) *git.Repository {
169204
tempDir, err := os.MkdirTemp("", function.Name)
170205
Expect(err).NotTo(HaveOccurred())
171206

@@ -176,8 +211,31 @@ func createTmpGitRepo(function functions.Function) *git.Repository {
176211
err = os.WriteFile(funcYamlPath, f, 0644)
177212
Expect(err).NotTo(HaveOccurred())
178213

179-
return &git.Repository{
214+
opts := &git.Repository{
180215
CloneDir: tempDir,
181-
SubPath: ".",
216+
}
217+
218+
for _, repoOption := range repoOptions {
219+
repoOption(opts)
220+
}
221+
222+
return opts
223+
}
224+
225+
func WithRepoOptionSubPath(subPath string) RepoOption {
226+
return func(repo *git.Repository) {
227+
repo.SubPath = subPath
228+
}
229+
}
230+
231+
func WithRepoOptionBranch(branch string) RepoOption {
232+
return func(repo *git.Repository) {
233+
repo.Branch = branch
234+
}
235+
}
236+
237+
func WithRepoOptionCommit(commit string) RepoOption {
238+
return func(repo *git.Repository) {
239+
repo.Commit = commit
182240
}
183241
}

internal/git/manager.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
4444
return nil, fmt.Errorf("failed to create temporary directory: %w", err)
4545
}
4646

47-
_, err = git.PlainCloneContext(ctx, targetDir, &git.CloneOptions{
47+
repo, err := git.PlainCloneContext(ctx, targetDir, &git.CloneOptions{
4848
URL: repoUrl,
4949
ReferenceName: plumbing.ReferenceName(reference),
5050
SingleBranch: true,
@@ -55,9 +55,16 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
5555
return nil, fmt.Errorf("failed to clone repo: %w", err)
5656
}
5757

58+
head, err := repo.Head()
59+
if err != nil {
60+
return nil, fmt.Errorf("failed to find head: %w", err)
61+
}
62+
5863
return &Repository{
5964
CloneDir: targetDir,
6065
SubPath: subPath,
66+
Commit: head.Hash().String(),
67+
Branch: reference,
6168
}, nil
6269
}
6370

internal/git/repository.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
type Repository struct {
99
CloneDir string
1010
SubPath string
11+
Commit string
12+
Branch string
1113
}
1214

1315
func (r *Repository) Path() string {

0 commit comments

Comments
 (0)