diff --git a/Dockerfile b/Dockerfile new file mode 100644 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM golang:1.25-bookworm AS builder + +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=1 GOOS=linux go build -trimpath -ldflags="-s -w" -o /tack . + +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /tack /usr/local/bin/tack + +RUN useradd -r -u 1000 -m tack +USER tack + +EXPOSE 8080 + +ENTRYPOINT ["/usr/local/bin/tack"] diff --git a/deploy/deployment.yaml b/deploy/deployment.yaml new file mode 100644 --- /dev/null +++ b/deploy/deployment.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tack + namespace: tack +spec: + replicas: 1 # SQLite is single-writer; do not scale above 1 + selector: + matchLabels: + app: tack + template: + metadata: + labels: + app: tack + spec: + serviceAccountName: tack + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: tack + image: atcr.io/dsx.sh/tack:latest + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + env: + - name: TACK_LISTEN_ADDR + value: ":8080" + - name: TACK_DB_PATH + value: "/var/lib/tack/tack.db" + - name: TACK_TEKTON_ENABLED + value: "1" + - name: TACK_TEKTON_NAMESPACE + value: "tekton-pipelines" + envFrom: + - secretRef: + name: tack + volumeMounts: + - name: db + mountPath: /var/lib/tack + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 5 + periodSeconds: 30 + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 2 + periodSeconds: 10 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + memory: 256Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + volumes: + - name: db + persistentVolumeClaim: + claimName: tack-db diff --git a/deploy/hello-world.yaml b/deploy/hello-world.yaml new file mode 100644 --- /dev/null +++ b/deploy/hello-world.yaml @@ -0,0 +1,57 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: hello-world +spec: + description: Simple Pipeline for validating Tack-created Tekton PipelineRuns. + params: + - name: message + type: string + default: Hello from Tack + - name: name + type: string + default: world + tasks: + - name: say-hello + taskRef: + name: hello-world + params: + - name: message + value: $(params.message) + - name: name + value: $(params.name) + - name: finish + runAfter: + - say-hello + taskRef: + name: hello-world-finish + params: + - name: name + value: $(params.name) +--- +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: hello-world-inline +spec: + description: Single inline-task Pipeline for the smallest Tack smoke test. + params: + - name: message + type: string + default: Hello from Tack + tasks: + - name: say-hello + taskSpec: + params: + - name: message + type: string + steps: + - name: hello + image: busybox:1.36 + script: | + #!/bin/sh + set -eu + echo "$(params.message)" + params: + - name: message + value: $(params.message) diff --git a/deploy/kustomization.yaml b/deploy/kustomization.yaml new file mode 100644 --- /dev/null +++ b/deploy/kustomization.yaml @@ -0,0 +1,11 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: tack +resources: + - namespace.yaml + - serviceaccount.yaml + - rbac.yaml + - pvc.yaml + - secret.yaml + - deployment.yaml + - service.yaml diff --git a/deploy/namespace.yaml b/deploy/namespace.yaml new file mode 100644 --- /dev/null +++ b/deploy/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: tack + labels: + atcr.io-image: "true" diff --git a/deploy/pvc.yaml b/deploy/pvc.yaml new file mode 100644 --- /dev/null +++ b/deploy/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: tack-db + namespace: tack +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi diff --git a/deploy/rbac.yaml b/deploy/rbac.yaml new file mode 100644 --- /dev/null +++ b/deploy/rbac.yaml @@ -0,0 +1,34 @@ +# Role in tekton-pipelines so tack can manage PipelineRuns and read pod logs there. +# The RoleBinding references tack's ServiceAccount cross-namespace. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: tack + namespace: tekton-pipelines +rules: + - apiGroups: ["tekton.dev"] + resources: ["pipelineruns"] + verbs: ["create", "get", "list", "watch"] + - apiGroups: ["tekton.dev"] + resources: ["taskruns"] + verbs: ["list"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: tack + namespace: tekton-pipelines +subjects: + - kind: ServiceAccount + name: tack + namespace: tack +roleRef: + kind: Role + name: tack + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/secret.yaml b/deploy/secret.yaml new file mode 100644 --- /dev/null +++ b/deploy/secret.yaml @@ -0,0 +1,15 @@ +# Rename to secret.yaml and fill in real values before applying. +# Do not commit populated secrets to version control. +apiVersion: v1 +kind: Secret +metadata: + name: tack + namespace: tack +type: Opaque +stringData: + TACK_HOSTNAME: "tack.example.com" + TACK_OWNER_DID: "did:plc:1234" + # Uncomment to enable Buildkite provider: + # TACK_BUILDKITE_TOKEN: "" + # TACK_BUILDKITE_ORG: "" + # TACK_BUILDKITE_WEBHOOK_SECRET: "" diff --git a/deploy/service.yaml b/deploy/service.yaml new file mode 100644 --- /dev/null +++ b/deploy/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: tack + namespace: tack +spec: + selector: + app: tack + ports: + - name: http + port: 80 + targetPort: http diff --git a/deploy/serviceaccount.yaml b/deploy/serviceaccount.yaml new file mode 100644 --- /dev/null +++ b/deploy/serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tack + namespace: tack