owned this note
owned this note
Published
Linked with GitHub
# Shipwright Beta API Workshop
## Full build strategy with all possible fields
**NOTE**: DO NOT EDIT before workshop unless something is missing.
```yaml
---
apiVersion: shipwright.io/v1alpha1
kind: ClusterBuildStrategy
metadata:
name: strategy-name
spec:
parameters:
- name: array-argument
description: "The description of the parameter."
# optional, default string
type: array
# optional
defaults: []
- name: string-argument
description: "The description of the parameter."
type: string
# optional
default: registry
volumes:
- name: some-volume
description: "The description of the volume."
# optional, default false
overridable: true
# is just an example, the whole VolumeSource is possible here
emptyDir: {}
steps:
# These are the _only_ options supported, this is not the full Container spec
- name: some-name
image: alpine:latest
imagePullPolicy: Always
workingDir: $(params.shp-source-root)
command:
- /some-command
args:
- some-arg
env:
- name: ENV_NAME
value: SOME_VALUE
securityContext:
runAsUser: 0
capabilities:
add:
- CHOWN
- DAC_OVERRIDE
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1m
memory: 2Gi
volumeMounts:
- name: some-volume
mountPath: /somepath
readOnly: false
```
## Full build with all possible fields
**NOTE**: DO NOT EDIT before workshop unless something is missing.
```yaml
apiVersion: shipwright.io/v1alpha1
kind: Build
metadata:
name: some-build
annotations:
# optional, default "false"
build.shipwright.io/verify.repository: "true"
spec:
trigger:
when:
- name: a-github-trigger
type: GitHub
github:
events:
- PullRequest|Push
# optional
branches:
- branch-1
- branch-2
- name: an-image-trigger
type: Image
image:
names:
- image-1
- image-2
- name: a-pipeline-trigger-based-on-name
type: Pipeline
objectRef:
name: some-pipeline-name
# optional
status:
- SomeStatus
- name: a-pipeline-trigger-based-on-labels
type: Pipeline
objectRef:
selector:
aLabel: aValue
# optional
status:
- SomeStatus
# optional
triggerSecret: webhook-token-secret
# Bundle
source:
ociArtifact:
image: ghcr.io/shipwright-io/sample-go/source-bundle:latest
# optional, default Never
prune: AfterPull|Never
pullSecret: my-registry-secret
contextDir: docker-build
# Git
source:
git:
url: git@github.com:shipwright-io/build.git
# optional, default is default branch
revision: v0.10.0
# optional
cloneSecret: my-ssh-secret
# optional
contextDir: docker-build
strategy:
name: buildah
# optional, default ClusterBuildStrategy
kind: BuildStrategy
# optional
paramValues:
- name: simple-string
value: "Some value"
- name: string-from-configmap
configMapValue:
name: configmap-name
key: key-in-configmap
# optional
format: KEY=${CONFIGMAP_VALUE}
- name: string-from-secret
secretValue:
name: secret-name
key: key-in-secret
# optional
format: KEY=${SECRET_VALUE}
- name: array-with-everything
value:
- value: simple-item
- configMapValue:
name: configmap-name
key: key-in-configmap
# optional
format: KEY=${CONFIGMAP_VALUE}
- secretValue:
name: secret-name
key: key-in-secret
# optional
format: KEY=${SECRET_VALUE}
# optional
volumes:
- name: my-volume-override
# is just an example, the whole VolumeSource is possible here
emptyDir: {}
# optional
env:
# We here use the Kubernetes EnvVar
- name: AN_ENV
value: "My value"
- name: POD_NAME
valueFrom:
# More options available in EnvVarSource
fieldRef:
fieldPath: ".metadata.name"
# optional, default 10m
timeout: 5m
output:
image: image-registry.openshift-image-registry.svc:5000/build-examples
/taxi-app
# optional
pushSecret: some-registry-secret
# optional
annotations:
some.domain/my-annotation: "Some annotation value"
# optional
labels:
myLabel: "Custom label value"
# optional
retention:
# optional - "false" means that a BuildRun is deleted when the parent Build is deleted
keepOrphaned: true
# optional
failedLimit: 3
# optional
succeededLimit: 3
# optional
ttlAfterFailed: 48h
# optional
ttlAfterSucceeded: 8h
```
## Full buildrun with all possible fields
**NOTE**: DO NOT EDIT before workshop unless something is missing.
```yaml
apiVersion: shipwright.io/v1alpha1
kind: BuildRun
metadata:
name: some-buildrun
spec:
build:
# optional, mutually exclusive with spec
name: some-build
# optional, mutually exclusive with name
spec: {} # see Build.spec
# optional, mutually exclusive with build.spec
paramValues: [] # see Build.paramValues
# optional, mutually exclusive with build.spec
env: [] # see Build.env
# optional, default with name=pipeline and fallback to default
# .generated is a special value, replaces `generate: true`
serviceAccount: ".generated"
# optional, mutually exclusive with build.spec
timeout: 5m
# optional
state: BuildRunCanceled
# optional, mutually exclusive with build.spec
retention:
# optional
ttlAfterFailed: 48h
# optional
ttlAfterSucceeded: 8h
# optional, mutually exclusive with build.spec
volumes: [] # see Build.volumes
status:
buildSpec: {} # see Build.spec
taskRunName: some-buildrun-taskrun
startTime: 2022-02-22T22:22:22Z
completionTime: 2022-02-22T22:22:22Z
conditions:
- type: Succeeded
status: True|False|Unknown
lastTransitionTime: 2022-02-22T22:22:22Z
reason: Succeeded|BuildNotFound|...
message: "Some explanatory text."
# deprecated
failedAt:
pod: some-buildrun-taskrun-pod
container: step-build-and-push
failureDetails:
location:
pod: some-buildrun-taskrun-pod
container: step-build-and-push
reason: BuildStrategyDefinedFailureReason
message: "Explanatory details for the reason."
source:
git:
commitSha: abcd
commitAuthor: "Some Name"
branchName: main
output:
digest: sha:....
size: 2196391
```
## API conventions
* Optional non-array fields in spec are always pointers.
* Use unique `name` fields in arrays to the furthest extent possible. Utilize `patchMergeKey=name` and `patchStrategy=merge,retainKeys` annotations to enable `kubectl patch` on arrays.
*
## List of proposed change requests:
### Example: Title
Scope: API Convention|BuildStrategy|Build|BuildRun
Originator: Put in your name
What: Put in your proposal. Note: this is about changing our API objects to become nicer and consistent. It is NOT about introducing features.
Migration: assess if the old version can be migrated to the new version and vice versa without any loss of information
### Add convention about lists different elements - ACCEPTED
Scope: API Convention
Originator: Sascha
What: Today, we are inconsistent in that. Basically it is about all arrays that we have which contain definitions of different kinds. I suggest that we:
* Always have a `name` field. This is also helpful for `kubectl patch` I think to correlate items if we also specify the following on the array property:
```go
// +patchMergeKey=name
// +patchStrategy=merge,retainKeys
```
~~* do NOT have a kind or type field. Inherited pattern for volumes is the example; type is implicitly defined.~~ Moved to separate proposal.
* Have different keys for the different element kinds, all are pointers, exactly one must be set.
Examples:
* We follow this pattern today already for `spec.volumes`.
```yaml
spec:
volumes:
- name: some-volume
hostPath:
path: /data
- name: some-other-volume
emptyDir: {}
```
* We should imo do this for `spec.sources`, see [below](#Build-sources)
* We should imo do this for `spec.triggers` = remove `spec.trigger.when[].type`
Migration: no problem in both directions because type is redundant information.
### Add convention regarding 3rd party service credentials - ACCEPTED
Scope: API Convention
Originator: Adam Kaplan
What: We currently use a `credentials` object to reference a secret that used for authentication and authorization with 3rd party services. This proposes replacing the object reference with a simple field. Each field indicates the reason why the secret is provided.
git clone example:
```yaml
spec:
source:
git:
url: <>
cloneSecret: my-git-creds
```
image push example:
```yaml
spec:
output:
image: image-name
pushSecret: my-push-creds
```
Concern - using `<reason>Secret` will result in false positives from code scanners.
`<reason>SecretName` may result in fewer false positives. This was tested and not confirmed.
### Rename buildSteps to steps - ACCEPTED
Scope: BuildStrategy
Originator: Sascha
What: I think that `steps` is shorter but still descriptive enough. For consistency we can then rename the underlying Go type from `BuildStep` to `Step`
Migration: no problem in both directions
### Remove inline Container in BuildStep - ACCEPTED
Scope: BuildStrategy
Originator: Sascha
What: change `BuildStep` to not anymore have an inline `Container` object, but instead put in only those fields that we copy into the TaskRun. Those today are `name`, `image`, `imagePullPolicy`, `workingDir`, `command`, `args`, `env`, `resources`, `securityContext`, and `volumeMounts`. It will then look like this:
```yaml
spec:
buildSteps:
- name: some-name
image: alpine:latest
# Optional
imagePullPolicy: Always
# Optional
workingDir: $(params.shp-source-root)
# Optional
command:
- /some-command
# Optional
args:
- some-arg
# Optional
env:
- name: ENV_NAME
value: SOME_VALUE
# Optional
resources:
limits:
cpu: "1"
memory: 1G
# Optional
securityContext:
runAsUser: 0
capabilities:
add:
- CHOWN
- DAC_OVERRIDE
# Optional
volumeMounts:
- name: some-volume
mountPath: /somepath
readOnly: false
```
Migration: Possible in both directions. When migrating from alpha to beta we potentially throw away other fields that could theoretically be defined such as `EnvFrom` or `LivenessProbe`, but given we never forwarded those to the TaskRun anyway, we do not loose anything. In the future, we can revisit if we should forward additional fields that would make sense such as for example `Lifecycle`.
Notes: We should try and keep our API independent of dependencies (k8s, Tekton), unless we are comfortable fully supporting a given dependent field.
Examples - not exposing the `script` field in Tekton steps, limiting `EnvFrom`.
### Move build-run-deletion annotation to spec.retention - ACCEPTED
Scope: Build
Originator: Sascha
What: introduce `.spec.retention.atBuildDeletion` of type `bool` with default `false`
Migration: no problem in both directions
```yaml
kind: Build
spec:
retention:
keepOrphaned: true
failedLimit: 5
succeededLimit: 5
```
Suggestion - change default behavior to set the owner reference on BuildRuns, use `retention` field to opt out of this behavior.
Interim is `spec.retention.keepOrphaned`. Community can continue to brainstorm names for this field.
### Build sources - DECLINED in favor of "Revert sources"
Scope: Build
Originator: Sascha
What: Remove source, go forward with sources, and move contextDir to `.spec.strategy` (or `.spec`?):
```yaml
spec:
# optional (means no sources is valid)
sources:
- name: a-git-source
git:
url: git@github.com:shipwright-io/build.git
# optional, default is default branch
revision: v0.10.0
# optional
# TBD: how ?
secretName: my-ssh-secret
- name: an-http-source
http:
url: https://raw.githubusercontent.com/shipwright-io/community/main/assets/icons/png/shipwright-logo-1color-darkbg-128.png
- name: a-bundle-source
container:
url: ghcr.io/shipwright-io/sample-go/source-bundle:latest
# optional
# TBD: how ?
secretName: my-ssh-secret
- name: a-local-source
local:
# optional
timeout: 30s
strategy:
# optional
contextDir: my-context-dir
```
Migration: there will only be problems if somebody defines a Build with a Git and a Bundle source, or with more than one of them. This cannot be handled. But we will need to discuss whether this is at all allowed anyway.
### Revert sources, only have `spec.source` - ACCEPTED
Scope: Build
Originator: Adam Kaplan
What: A counter-proposal to "Build Sources" - we should only support a single source per build/buildRun, but allow multiple types within `source`.
git example:
```yaml
spec:
source:
# optional, if the working directory should be a subdirectory within the given source
contextDir: app
type: Git
git:
url: git@github.com:shipwright-io/build.git
# optional, default is default branch
revision: v0.10.0
# optional, needed for private repositories
cloneSecret: my-ssh-secret
```
local example:
```yaml
spec:
source:
type: Local
contextDir: src
local:
timeout: 5m
```
bundle (container image) example. Rename to "ociArtifact":
```yaml
spec:
source:
type: ContainerImage
# optional, if the input source should be a subdirectory within the container image
contextDir: /app-root/bundle
containerImage:
image: ghcr.io/shipwright-io/sample-go/source-bundle:latest
# optional, needed for private registries
pullSecret: my-ghcr-pull-secret
prune: true # existing API
```
Migration: Git and bundleContainer source builds will be able to migrate, perhaps with some re-mapping of YAML keys.
Local source builds will switch to using `spec.source.local` instead of `spec.sources[0].localCopy`.
HTTP sources would be dropped as a feature and no longer supported.
Builds with `spec.sources` and `spec.source` will not be able to migrate. Question - how common is this?
Suggestions:
- Move `contextDir` to be top level (under "source")
- BuildRun status should have `status.source`, where relevant information is populated. Example: `status.source.git.sha`, `status.source.ociArtifact.digest`
### Eliminate dockerfile field - ACCEPTED
Scope: Build
Originator: Sascha
What: Remove `.spec.dockerfile`
Migration: we will add a dockerfile parameter to all sample build strategies for Dockerfile-based builds. We can also continue to set the unofficial `$(params.DOCKERFILE)` for some time until we remove it to not break old build strategies. The rest is doable.
Note - some concerns regarding parameter and migration.
### Eliminate builder field - ACCEPTED
Scope: Build
Originator: Sascha
What: Remove `.spec.builder`
Migration: we will modify the s2i sample build strategies and add a parameter for the image name a volume for the secret. But I do not see how we can support a good migration path here especially in the build strategy.
### Eliminate volume description on Build - ACCEPTED
Scope: Build
Originator: Sascha
What: remove `.spec.volumes[].description`. This brings it in synchronization with parameters where the description is only provided in the strategy and cannot be overwritten.
Migration: not possible because of removal
### Remove ~~`registered`~~ status from Build and BuildStrategy/ClusterBuildStrategy - ACCEPTED
Scope: Build
Originator: Adam Kaplan
What: Remove `status` from objects which do not result in executing code - `Build`, `BuildStrategy`, and `ClusterBuildStrategy`.
Migration: No direct API migration. Clients which report this information should drop these fields.
Notes:
- Current checks verify that the Build object is internally consistent.
- We have a feature where a Secret can be watched to re-validate Build objects.
- Validations should happen when BuildRun is created.
TODO: Deprecate `status` in alpha API?
### Rename latestTaskRunRef to taskRunName - ACCEPTED
Scope: BuildRun
Originator: Sascha
What: rename `.status.latestTaskRunRef` to `.status.taskRunName`
Migration: no problem in both directions
Notes:
- Potential new API convention - should references to objects include `Name` in the suffix? Otherwise `.status.taskRun` would be viable.
Results of the detect-secrets investigation will inform this decision.
### Remove generated service account from API - ACCEPTED
Scope: BuildRun
Originator: Adam Kaplan
What: Remove API-level support for generating a service account. Instead, use a string reference to a service account in a BuildRun, and eventually the Build object as well. Allow the ".generated" service account value, which continues the existing behavior until it is deprecated/removed.
Migration: serviceAccount.generated = true can move to `serviceAccount = .generated`.
```yaml
spec:
serviceAccount(Name): my-service-account
serviceAccount(Name): .generated # compat value until we implemented the generated service account removal
```
Notes:
- Eventually allow to define it also on the Build
- Motivation of this feature is that it allows dedicated service accounts to set up image push secrets via Tekton's creds-init feature. We don't want to pollute service accounts with linked secrets.
- We need to keep the existing behavior, but this can be done with a special ".generated" value for the service account name. Once we remove the dependency on creds-init, we can drop this feature by deprecating/removing support for the ".generated" service account (name).
- ".generated" is not a valid Kubernetes object reference, so we can use it as a special value.
### Consolidate buildRef and buildSpec - ACCEPTED
Scope: BuildRun
Originator: Sascha
What: move the referenced (`.spec.buildRef.name`) or inline build specification (`.spec.buildSpec`) into one top-level. One can then specify either
```yaml
spec:
build:
name: a-build
```
or
```yaml
spec:
build:
spec: {} # full build spec
```
This makes it behave consistent with `spec.strategy` on the Build.
Migration: no problem in both directions
### Drop Kind/Type fields - DECLINED
Scope: API Convention
Originator: Sascha
What: do NOT have a kind or type field. Inherited pattern for volumes is the example; type is implicitly defined.
### Use Kind/Type fields as type discriminators - ACCEPTED
Scope: API Convention
Originator: Adam Kaplan
What: Use "type discriminators" if an API object has some form of implied polymorphism. For example, source types or volume sources.
Counter-proposal to "Drop Kind/Type fields"
Problem: volumeSource is not maintained by us so we would have a problem to provide a type field - we could introduce our own volumeSource with selected options only.
Proposal: only introduce type field when we own the options (for source and triggers but not for volume sources) -> we go that path