Skip to content

Commit ff62ddb

Browse files
committed
api: rename repository branch and path to revision and dir
Breaking change to v1alpha1: - spec.repository.branch is now spec.repository.revision. It takes a branch name or a full ref such as refs/tags/v1.0.0. Bare tag names and commit hashes follow once sources are read with func's NewFunctionFromGit. - spec.repository.path is now spec.repository.dir, matching func's build.source.dir and --source-dir. - status.git.resolvedBranch is now status.git.resolvedRevision. The operator no longer defaults an empty revision to main: the clone takes the remote's default branch and resolvedRevision reports its name, so repositories whose default branch is not main work without a revision. The sample CR used fields the CRD never had (spec.source.repositoryUrl, spec.registry.path) and is rewritten against the current schema. knative/func's Function CR sync still writes branch and path through func-operator v0.2.1. The API server drops those unknown fields, so func needs a matching change.
1 parent 7f19e6d commit ff62ddb

11 files changed

Lines changed: 71 additions & 52 deletions

File tree

‎README.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ kubectl get func my-function -o yaml
204204

205205
The status will include:
206206
- Function name and conditions
207-
- Git information (branch, commit, last checked time)
207+
- Git information (revision, commit, last checked time)
208208
- Deployment details (image, runtime, build time, deployer)
209209
- Middleware status (current and available versions, auto-update settings, pending rebuild status)
210210
- Service status (URL and readiness)
@@ -213,7 +213,7 @@ The status will include:
213213

214214
### Functions in Monorepos
215215

216-
For functions located in a subdirectory of a repository (e.g., in a monorepo), use the `repository.path` field to specify the path to your function:
216+
For functions located in a subdirectory of a repository (e.g., in a monorepo), use the `repository.dir` field to specify the directory that holds your function:
217217

218218
```yaml
219219
apiVersion: functions.dev/v1alpha1
@@ -224,7 +224,7 @@ metadata:
224224
spec:
225225
repository:
226226
url: https://github.com/your-org/your-monorepo.git
227-
path: functions/my-function
227+
dir: functions/my-function
228228
authSecretRef:
229229
name: git-credentials
230230
registry:
@@ -291,8 +291,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and contr
291291
| Field | Type | Required | Description |
292292
|-----------------------------|---------|----------|--------------------------------------------------------------------------------------------------|
293293
| `repository.url` | string | Yes | URL of the Git repository. Supports HTTPS, HTTP, SSH (`ssh://`), and SCP-style (`git@host:path`) |
294-
| `repository.branch` | string | No | Branch of the repository |
295-
| `repository.path` | string | No | Path to the function inside the repository. Defaults to "." |
294+
| `repository.revision` | string | No | Revision to build: a branch name or a full ref such as `refs/tags/v1.0.0`. Defaults to the repository's default branch |
295+
| `repository.dir` | string | No | Directory within the repository that holds the function (its `func.yaml`). Defaults to the repository root |
296296
| `repository.authSecretRef` | object | No | Reference to the auth secret for private repository authentication |
297297
| `registry.authSecretRef` | object | No | Reference to the secret containing credentials for registry authentication |
298298
| `autoUpdateMiddleware` | boolean | No | Defines if the operator should rebuild when outdated middleware is detected. When not specified, defaults to the operator-wide setting in the `func-operator-controller-config` ConfigMap (default: `true`). Function-level setting takes precedence over operator default |
@@ -303,7 +303,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and contr
303303
|-------|------|-------------|
304304
| `name` | string | Function name from metadata |
305305
| `conditions` | array | Status conditions (see below) |
306-
| `git.resolvedBranch` | string | Git branch that is being monitored |
306+
| `git.resolvedRevision` | string | Revision that was checked out: `repository.revision`, or the default branch name when that is empty |
307307
| `git.observedCommit` | string | Latest Git commit SHA observed |
308308
| `git.lastChecked` | timestamp | Last time the repository was checked |
309309
| `deployment.image` | string | Container image of the deployed function |

‎api/v1alpha1/function_defaults.go‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ func (r *FunctionSpecRepository) SetDefaults(ctx context.Context) {
2323
if r == nil {
2424
return
2525
}
26-
27-
if r.Branch == "" {
28-
r.Branch = "main"
29-
}
3026
}
3127

3228
func (r *FunctionSpecRegistry) SetDefaults(ctx context.Context) {

‎api/v1alpha1/function_types.go‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,17 @@ type FunctionSpecRepository struct {
5656
URL string `json:"url"`
5757

5858
// +kubebuilder:validation:Optional
59-
// Branch of the repository
60-
Branch string `json:"branch,omitempty"`
59+
// Revision of the repository to build: a branch name or a full ref such as refs/tags/v1.0.0.
60+
// Defaults to the repository's default branch.
61+
Revision string `json:"revision,omitempty"`
6162

6263
// AuthSecretRef defines the reference to the auth secret in case the repository is private and needs authentication
6364
AuthSecretRef *v1.LocalObjectReference `json:"authSecretRef,omitempty"`
6465

6566
// +kubebuilder:validation:Optional
66-
// Path points to the function inside the repository. Defaults to "."
67-
Path string `json:"path,omitempty"`
67+
// Dir is the directory within the repository that holds the function (its func.yaml).
68+
// Defaults to the repository root.
69+
Dir string `json:"dir,omitempty"`
6870
}
6971

7072
type FunctionSpecRegistry struct {
@@ -92,9 +94,11 @@ type FunctionStatusHistoryEntry struct {
9294
}
9395

9496
type FunctionStatusGit struct {
95-
ResolvedBranch string `json:"resolvedBranch,omitempty"`
96-
ObservedCommit string `json:"observedCommit,omitempty"`
97-
LastChecked metav1.Time `json:"lastChecked,omitempty"`
97+
// ResolvedRevision is the revision that was checked out: spec.repository.revision,
98+
// or the name of the default branch when that is empty.
99+
ResolvedRevision string `json:"resolvedRevision,omitempty"`
100+
ObservedCommit string `json:"observedCommit,omitempty"`
101+
LastChecked metav1.Time `json:"lastChecked,omitempty"`
98102
}
99103

100104
type FunctionStatusDeployment struct {

‎config/crd/bases/functions.dev_functions.yaml‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,15 @@ spec:
101101
type: string
102102
type: object
103103
x-kubernetes-map-type: atomic
104-
branch:
105-
description: Branch of the repository
104+
dir:
105+
description: |-
106+
Dir is the directory within the repository that holds the function (its func.yaml).
107+
Defaults to the repository root.
106108
type: string
107-
path:
108-
description: Path points to the function inside the repository.
109-
Defaults to "."
109+
revision:
110+
description: |-
111+
Revision of the repository to build: a branch name or a full ref such as refs/tags/v1.0.0.
112+
Defaults to the repository's default branch.
110113
type: string
111114
url:
112115
description: URL of the Git repository containing the function
@@ -196,7 +199,10 @@ spec:
196199
type: string
197200
observedCommit:
198201
type: string
199-
resolvedBranch:
202+
resolvedRevision:
203+
description: |-
204+
ResolvedRevision is the revision that was checked out: spec.repository.revision,
205+
or the name of the default branch when that is empty.
200206
type: string
201207
type: object
202208
history:

‎config/samples/v1alpha1_function.yaml‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ metadata:
77
name: function-sample
88
namespace: default
99
spec:
10-
source:
11-
repositoryUrl: https://github.com/your-org/your-function.git
10+
repository:
11+
url: https://github.com/your-org/your-function.git
12+
# optional: branch name or full ref (e.g. refs/tags/v1.0.0); defaults to the default branch
13+
revision: main
14+
# optional: directory holding the function's func.yaml; defaults to the repository root
15+
dir: .
1216
authSecretRef:
1317
name: git-credentials
1418
registry:
15-
path: quay.io/your-username/my-function
1619
authSecretRef:
17-
name: registry-credentials
20+
name: registry-credentials

‎docs/architecture.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ Defined in `api/v1alpha1/function_types.go`. A `Function` resource represents a
2222

2323
**Spec** (user-provided):
2424
- `repository.url` — Git repository containing the function source
25-
- `repository.branch` — Branch to track (optional, defaults to repo default)
26-
- `repository.path` — Subdirectory within the repo (for monorepos)
25+
- `repository.revision` - Branch name or full ref to build (optional, defaults to the repo's default branch)
26+
- `repository.dir` - Directory within the repo that holds the function (for monorepos)
2727
- `repository.authSecretRef` — Secret for private repo authentication
2828
- `registry.authSecretRef` — Secret for container registry authentication
2929
- `autoUpdateMiddleware` — Override operator default (optional)
3030

3131
**Status** (operator-managed):
32-
- `git` — Resolved branch, observed commit, last check time
32+
- `git` - Resolved revision, observed commit, last check time
3333
- `deployment` — Current image, build time, deployer, runtime
3434
- `middleware` — Current/available versions, auto-update config, rebuild state
3535
- `service` — URL and readiness of the underlying Knative Service

‎internal/controller/function_controller.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func (r *FunctionReconciler) prepareSource(ctx context.Context, function *v1alph
193193
}
194194
}
195195

196-
repo, err := r.GitManager.CloneRepository(ctx, function.Spec.Repository.URL, function.Spec.Repository.Path, function.Spec.Repository.Branch, gitAuthSecret.Data)
196+
repo, err := r.GitManager.CloneRepository(ctx, function.Spec.Repository.URL, function.Spec.Repository.Dir, function.Spec.Repository.Revision, gitAuthSecret.Data)
197197
if err != nil {
198198
function.MarkSourceNotReady("GitCloneFailed", "Failed to clone repository: %s", err.Error())
199199
return nil, nil, fmt.Errorf("failed to setup git repository: %w", err)
@@ -208,7 +208,7 @@ func (r *FunctionReconciler) prepareSource(ctx context.Context, function *v1alph
208208
// Source is ready - git clone and metadata read succeeded
209209
function.MarkSourceReady()
210210

211-
function.Status.Git.ResolvedBranch = repo.Branch
211+
function.Status.Git.ResolvedRevision = repo.Revision
212212
function.Status.Git.ObservedCommit = repo.Commit
213213
function.Status.Git.LastChecked = metav1.Now()
214214

‎internal/controller/function_controller_test.go‎

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ var _ = Describe("Function Controller", func() {
5858

5959
defaultSpec := functionsdevv1alpha1.FunctionSpec{
6060
Repository: functionsdevv1alpha1.FunctionSpecRepository{
61-
URL: "https://github.com/foo/bar",
62-
Branch: "my-branch",
61+
URL: "https://github.com/foo/bar",
62+
Revision: "my-branch",
6363
},
6464
}
6565

@@ -177,7 +177,7 @@ var _ = Describe("Function Controller", func() {
177177
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "my-branch", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
178178
},
179179
}),
180-
Entry("should use main as default branch", reconcileTestCase{
180+
Entry("should clone the default branch when no revision is set", reconcileTestCase{
181181
spec: functionsdevv1alpha1.FunctionSpec{
182182
Repository: functionsdevv1alpha1.FunctionSpecRepository{
183183
URL: "https://github.com/foo/bar",
@@ -191,15 +191,19 @@ var _ = Describe("Function Controller", func() {
191191
}, nil)
192192
funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v1.0.0", nil)
193193

194-
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
194+
// an empty revision clones the remote's default branch, which the git manager reports back
195+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}, WithRepoOptionRevision("trunk")), nil)
196+
},
197+
statusChecks: func(status *functionsdevv1alpha1.FunctionStatus) {
198+
Expect(status.Git.ResolvedRevision).Should(Equal("trunk"))
195199
},
196200
}),
197201

198202
Entry("should contain the git information in the status", reconcileTestCase{
199203
spec: functionsdevv1alpha1.FunctionSpec{
200204
Repository: functionsdevv1alpha1.FunctionSpecRepository{
201-
URL: "https://github.com/foo/bar",
202-
Branch: "my-branch",
205+
URL: "https://github.com/foo/bar",
206+
Revision: "my-branch",
203207
},
204208
},
205209
configureMocks: func(funcMock *funccli.MockManager, gitMock *git.MockManager) {
@@ -210,10 +214,10 @@ var _ = Describe("Function Controller", func() {
210214
}, nil)
211215
funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v1.0.0", nil)
212216

213-
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)
217+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "my-branch", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}, WithRepoOptionRevision("my-branch"), WithRepoOptionCommit("foobar")), nil)
214218
},
215219
statusChecks: func(status *functionsdevv1alpha1.FunctionStatus) {
216-
Expect(status.Git.ResolvedBranch).Should(Equal("my-branch"))
220+
Expect(status.Git.ResolvedRevision).Should(Equal("my-branch"))
217221
Expect(status.Git.ObservedCommit).Should(Equal("foobar"))
218222
},
219223
}),
@@ -233,7 +237,7 @@ var _ = Describe("Function Controller", func() {
233237
}, nil)
234238
funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v1.0.0", nil)
235239

236-
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{
240+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "", mock.Anything).Return(createTmpGitRepo(functions.Function{
237241
Name: "func-go",
238242
Runtime: "node",
239243
Deploy: functions.DeploySpec{
@@ -265,7 +269,7 @@ var _ = Describe("Function Controller", func() {
265269

266270
// no funcMock.EXPECT().Deploy call, as no redeploy expected!
267271

268-
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
272+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
269273
},
270274
operatorConfig: map[string]string{
271275
"autoUpdateMiddleware": "false",
@@ -289,7 +293,7 @@ var _ = Describe("Function Controller", func() {
289293

290294
// no funcMock.EXPECT().Deploy call, as no redeploy expected!
291295

292-
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
296+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
293297
},
294298
operatorConfig: map[string]string{
295299
"autoUpdateMiddleware": "true",
@@ -312,7 +316,7 @@ var _ = Describe("Function Controller", func() {
312316
}, nil)
313317
funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v2.0.0", nil)
314318

315-
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
319+
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
316320
},
317321
statusChecks: func(status *functionsdevv1alpha1.FunctionStatus) {
318322
Expect(status.Middleware.Current).Should(Equal("v2.0.0"))
@@ -551,8 +555,8 @@ var _ = Describe("Function Controller", func() {
551555
By("Creating the Function with registry authSecretRef")
552556
spec := functionsdevv1alpha1.FunctionSpec{
553557
Repository: functionsdevv1alpha1.FunctionSpecRepository{
554-
URL: "https://github.com/foo/bar",
555-
Branch: "my-branch",
558+
URL: "https://github.com/foo/bar",
559+
Revision: "my-branch",
556560
},
557561
Registry: functionsdevv1alpha1.FunctionSpecRegistry{
558562
AuthSecretRef: &v1.LocalObjectReference{
@@ -661,9 +665,9 @@ func WithRepoOptionSubPath(subPath string) RepoOption {
661665
}
662666
}
663667

664-
func WithRepoOptionBranch(branch string) RepoOption {
668+
func WithRepoOptionRevision(revision string) RepoOption {
665669
return func(repo *git.Repository) {
666-
repo.Branch = branch
670+
repo.Revision = revision
667671
}
668672
}
669673

‎internal/git/manager.go‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,17 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
8181
return nil, fmt.Errorf("failed to find head: %w", err)
8282
}
8383

84+
// An empty reference clones the remote's default branch: report its name.
85+
revision := reference
86+
if revision == "" && head.Name().IsBranch() {
87+
revision = head.Name().Short()
88+
}
89+
8490
return &Repository{
8591
CloneDir: targetDir,
8692
SubPath: subPath,
8793
Commit: head.Hash().String(),
88-
Branch: reference,
94+
Revision: revision,
8995
knownHostFile: tempFile,
9096
}, nil
9197
}

‎internal/git/repository.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ type Repository struct {
99
CloneDir string
1010
SubPath string
1111
Commit string
12-
Branch string
12+
Revision string
1313
knownHostFile string
1414
}
1515

0 commit comments

Comments
 (0)