Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions api/v1alpha1/buildjob_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ type ArtifactDestinationType string
type BuildJobPhase string

const (
SourceTypeGit SourceType = "git"
SourceTypePVC SourceType = "pvc"
SourceTypeGit SourceType = "git"
SourceTypePVC SourceType = "pvc"
SourceTypeRepo SourceType = "repo"

ArtifactDestinationPVC ArtifactDestinationType = "pvc"
ArtifactDestinationOCI ArtifactDestinationType = "oci"
Expand Down Expand Up @@ -66,13 +67,32 @@ type PVCSource struct {
Path string `json:"path,omitempty"`
}

// RepoSource configures a Google repo-tool manifest sync for AOSP/AAOS builds.
type RepoSource struct {
// +kubebuilder:validation:MinLength=1
ManifestURL string `json:"manifestUrl"`
// +optional
Branch string `json:"branch,omitempty"`
// +optional
ManifestName string `json:"manifestName,omitempty"`
// MirrorRef is the name of a PVC containing a local repo mirror; when set,
// repo init receives --reference=<mirror-path> to avoid re-downloading blobs.
// +optional
MirrorRef string `json:"mirrorRef,omitempty"`
// SyncJobs controls the -j parallelism passed to repo sync.
// +optional
SyncJobs int `json:"syncJobs,omitempty"`
}

type SourceSpec struct {
// +kubebuilder:validation:Enum=git;pvc
// +kubebuilder:validation:Enum=git;pvc;repo
Type SourceType `json:"type"`
// +optional
Git *GitSource `json:"git,omitempty"`
// +optional
PVC *PVCSource `json:"pvc,omitempty"`
// +optional
Repo *RepoSource `json:"repo,omitempty"`
}

type TargetSpec struct {
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ const (

AnnotationRunAt = "builder.sdv.cloud.redhat.com/run-at"

ManagedByValue = "bob"
DefaultServiceAccount = "pipeline"
ManagedByValue = "bob"
DefaultServiceAccount = "pipeline"
)
15 changes: 15 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ func (in *PVCSource) DeepCopy() *PVCSource {
return out
}

func (in *RepoSource) DeepCopyInto(out *RepoSource) { *out = *in }
func (in *RepoSource) DeepCopy() *RepoSource {
if in == nil {
return nil
}
out := new(RepoSource)
in.DeepCopyInto(out)
return out
}

func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
*out = *in
if in.Git != nil {
Expand All @@ -69,6 +79,11 @@ func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
*out = new(PVCSource)
**out = **in
}
if in.Repo != nil {
in, out := &in.Repo, &out.Repo
*out = new(RepoSource)
**out = **in
}
}
func (in *SourceSpec) DeepCopy() *SourceSpec {
if in == nil {
Expand Down
17 changes: 16 additions & 1 deletion config/crd/bases/builder.sdv.cloud.redhat.com_buildjobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ spec:
properties:
type:
type: string
enum: [git, pvc]
enum: [git, pvc, repo]
git:
type: object
required: [url]
Expand All @@ -84,6 +84,21 @@ spec:
path:
type: string
default: /
repo:
type: object
required: [manifestUrl]
properties:
manifestUrl:
type: string
minLength: 1
branch:
type: string
manifestName:
type: string
mirrorRef:
type: string
syncJobs:
type: integer
target:
type: object
properties:
Expand Down
18 changes: 9 additions & 9 deletions internal/buildapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,18 +523,18 @@ func (s *Server) handleArtifactDownload(w http.ResponseWriter, r *http.Request)

func toSummary(bj *buildv1alpha1.BuildJob) BuildJobSummary {
summary := BuildJobSummary{
Name: bj.Name,
Namespace: bj.Namespace,
Phase: string(bj.Status.Phase),
Board: bj.Spec.Target.Board,
Platform: bj.Spec.Target.Platform,
Architecture: bj.Spec.Target.Architecture,
Image: bj.Spec.Toolchain.Image,
CommitSHA: bj.Status.CommitSHA,
Name: bj.Name,
Namespace: bj.Namespace,
Phase: string(bj.Status.Phase),
Board: bj.Spec.Target.Board,
Platform: bj.Spec.Target.Platform,
Architecture: bj.Spec.Target.Architecture,
Image: bj.Spec.Toolchain.Image,
CommitSHA: bj.Status.CommitSHA,
ArtifactURI: bj.Status.ArtifactURI,
OCIArtifactRef: bj.Status.OCIArtifactRef,
OCIArtifactDigest: bj.Status.OCIArtifactDigest,
PipelineRun: bj.Status.CurrentPipelineRun,
PipelineRun: bj.Status.CurrentPipelineRun,
}

if bj.Spec.Source.Type == buildv1alpha1.SourceTypeGit && bj.Spec.Source.Git != nil {
Expand Down
24 changes: 12 additions & 12 deletions internal/buildapi/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ package buildapi
import buildv1alpha1 "github.com/centos-automotive-suite/bob/api/v1alpha1"

type BuildJobSummary struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Phase string `json:"phase"`
Board string `json:"board,omitempty"`
Platform string `json:"platform,omitempty"`
Architecture string `json:"architecture,omitempty"`
Image string `json:"image,omitempty"`
CommitSHA string `json:"commitSHA,omitempty"`
Name string `json:"name"`
Namespace string `json:"namespace"`
Phase string `json:"phase"`
Board string `json:"board,omitempty"`
Platform string `json:"platform,omitempty"`
Architecture string `json:"architecture,omitempty"`
Image string `json:"image,omitempty"`
CommitSHA string `json:"commitSHA,omitempty"`
ArtifactURI string `json:"artifactURI,omitempty"`
OCIArtifactRef string `json:"ociArtifactRef,omitempty"`
OCIArtifactDigest string `json:"ociArtifactDigest,omitempty"`
Stages []StageInfo `json:"stages,omitempty"`
PipelineRun string `json:"pipelineRun,omitempty"`
Source *SourceInfo `json:"source,omitempty"`
Age string `json:"age,omitempty"`
Stages []StageInfo `json:"stages,omitempty"`
PipelineRun string `json:"pipelineRun,omitempty"`
Source *SourceInfo `json:"source,omitempty"`
Age string `json:"age,omitempty"`
}

type StageInfo struct {
Expand Down
10 changes: 5 additions & 5 deletions internal/controller/buildjob_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ type BuildJobReconciler struct {
}

const (
runAtAnnotation = buildv1alpha1.AnnotationRunAt
conditionTypeSucceeded = "Succeeded"
conditionStatusTrue = "True"
conditionStatusFalse = "False"
conditionReasonRunning = "Running"
runAtAnnotation = buildv1alpha1.AnnotationRunAt
conditionTypeSucceeded = "Succeeded"
conditionStatusTrue = "True"
conditionStatusFalse = "False"
conditionReasonRunning = "Running"
)

func (r *BuildJobReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
Expand Down
1 change: 0 additions & 1 deletion internal/controller/buildjob_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,3 @@ func TestComputeOCIRef_NilOCI(t *testing.T) {
t.Fatalf("expected empty ref for nil OCI, got %q", ref)
}
}

4 changes: 2 additions & 2 deletions internal/controller/cache_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func (r *CacheReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
Name: pvcName,
Namespace: cache.Namespace,
Labels: map[string]string{
buildv1alpha1.LabelManagedBy: buildv1alpha1.ManagedByValue,
"builder.sdv.cloud.redhat.com/cache": cache.Name,
buildv1alpha1.LabelManagedBy: buildv1alpha1.ManagedByValue,
"builder.sdv.cloud.redhat.com/cache": cache.Name,
"builder.sdv.cloud.redhat.com/cache-type": string(cache.Spec.Type),
},
},
Expand Down
8 changes: 4 additions & 4 deletions internal/controller/toolchain_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,10 @@ echo "Toolchain image pushed: %s"
map[string]interface{}{
"name": "build-push",
"image": buildahImage,
"securityContext": map[string]interface{}{
"runAsNonRoot": true,
"runAsUser": int64(1000),
},
"securityContext": map[string]interface{}{
"runAsNonRoot": true,
"runAsUser": int64(1000),
},
"script": script,
},
},
Expand Down
104 changes: 99 additions & 5 deletions internal/tekton/pipelinerun_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ const (
TektonAPIVersion = "tekton.dev/v1"
PipelineRunKind = "PipelineRun"
GitCloneImage = "alpine/git:latest"
RepoInitImage = "python:3.12-slim"
OrasImage = "ghcr.io/oras-project/oras:v1.2.0"

workspaceName = "shared-workspace"
taskWorkspaceName = "ws"
taskCopySource = "copy-source"
taskClone = "clone"
taskRepoSync = "repo-sync"
mirrorVolumeName = "repo-mirror"
mirrorMountPath = "/mnt/mirror"
cacheVolumeName = "bob-cache"

DefaultFirmwareMediaType = "application/vnd.auto.firmware.layer.v1"
Expand Down Expand Up @@ -107,6 +111,11 @@ echo "Copied PVC source to workspace"
copyTask := buildPVCCopyTaskSpec(taskCopySource, image, copyScript, envVars, bj.Spec.Source.PVC.ClaimName)
tasks = append(tasks, copyTask)
prevStage = taskCopySource

case bj.Spec.Source.Type == buildv1alpha1.SourceTypeRepo && bj.Spec.Source.Repo != nil:
repoTask := buildRepoTaskSpec(bj.Spec.Source.Repo, envVars)
tasks = append(tasks, repoTask)
prevStage = taskRepoSync
}

for _, stage := range bj.Spec.Stages {
Expand Down Expand Up @@ -328,6 +337,87 @@ func buildPVCCopyTaskSpec(name, image, script string, envVars []interface{}, cla
}
}

func buildRepoTaskSpec(src *buildv1alpha1.RepoSource, envVars []interface{}) map[string]interface{} {
syncJobs := src.SyncJobs
if syncJobs <= 0 {
syncJobs = 4
}

initArgs := fmt.Sprintf("-u %s", ShellQuote(src.ManifestURL))
if src.Branch != "" {
initArgs += fmt.Sprintf(" -b %s", ShellQuote(src.Branch))
}
if src.ManifestName != "" {
initArgs += fmt.Sprintf(" -m %s", ShellQuote(src.ManifestName))
}
if src.MirrorRef != "" {
initArgs += fmt.Sprintf(" --reference=%s", ShellQuote(mirrorMountPath))
}

script := fmt.Sprintf(`#!/bin/sh
set -eu
# Install repo if not present (repo is a Python script, no compiled binary needed)
if ! command -v repo > /dev/null 2>&1; then
pip install --quiet repo
fi
cd $(workspaces.ws.path)
mkdir -p source
cd source
repo init %s
repo sync -j%d
`, initArgs, syncJobs)

allowPrivEsc := false

var volumes []interface{}
var volumeMounts []interface{}
if src.MirrorRef != "" {
volumes = append(volumes, map[string]interface{}{
"name": mirrorVolumeName,
"persistentVolumeClaim": map[string]interface{}{
"claimName": src.MirrorRef,
"readOnly": true,
},
})
volumeMounts = append(volumeMounts, map[string]interface{}{
"name": mirrorVolumeName,
"mountPath": mirrorMountPath,
"readOnly": true,
})
}

step := map[string]interface{}{
"name": "run",
"image": RepoInitImage,
"env": envVars,
"securityContext": map[string]interface{}{
"allowPrivilegeEscalation": allowPrivEsc,
},
"script": script,
}
if len(volumeMounts) > 0 {
step["volumeMounts"] = volumeMounts
}

taskSpec := map[string]interface{}{
"workspaces": []interface{}{
map[string]interface{}{"name": taskWorkspaceName, "mountPath": "/workspace"},
},
"steps": []interface{}{step},
}
if len(volumes) > 0 {
taskSpec["volumes"] = volumes
}

return map[string]interface{}{
"name": taskRepoSync,
"taskSpec": taskSpec,
"workspaces": []interface{}{
map[string]interface{}{"name": taskWorkspaceName, "workspace": workspaceName},
},
}
}

func buildTaskSpec(name, image, command string, envVars []interface{}, runAfter string, caches []buildv1alpha1.CacheMount) map[string]interface{} {
allowPrivEsc := false
step := map[string]interface{}{
Expand Down Expand Up @@ -442,11 +532,11 @@ func buildOCIArtifactTask(bj *buildv1alpha1.BuildJob, envVars []interface{}, run
ref := fmt.Sprintf("%s:%s", oci.Repository, tag)

annotations := map[string]string{
"org.opencontainers.image.title": bj.Name,
"vnd.auto.target.board": bj.Spec.Target.Board,
"vnd.auto.target.platform": bj.Spec.Target.Platform,
"vnd.auto.target.architecture": bj.Spec.Target.Architecture,
"vnd.auto.build.generation": fmt.Sprintf("%d", bj.Generation),
"org.opencontainers.image.title": bj.Name,
"vnd.auto.target.board": bj.Spec.Target.Board,
"vnd.auto.target.platform": bj.Spec.Target.Platform,
"vnd.auto.target.architecture": bj.Spec.Target.Architecture,
"vnd.auto.build.generation": fmt.Sprintf("%d", bj.Generation),
}
if bj.Spec.Target.Variant != "" {
annotations["vnd.auto.target.variant"] = bj.Spec.Target.Variant
Expand Down Expand Up @@ -588,6 +678,10 @@ func buildEnvVars(bj *buildv1alpha1.BuildJob) []interface{} {
if bj.Spec.Target.Variant != "" {
vars = append(vars, map[string]interface{}{"name": "BOB_VARIANT", "value": bj.Spec.Target.Variant})
}
if bj.Spec.Source.Type == buildv1alpha1.SourceTypeRepo && bj.Spec.Source.Repo != nil {
vars = append(vars, map[string]interface{}{"name": "BOB_MANIFEST_URL", "value": bj.Spec.Source.Repo.ManifestURL})
vars = append(vars, map[string]interface{}{"name": "BOB_MANIFEST_BRANCH", "value": bj.Spec.Source.Repo.Branch})
}
return vars
}

Expand Down
Loading
Loading