178 lines
6.5 KiB
YAML
178 lines
6.5 KiB
YAML
apiVersion: tekton.dev/v1
|
|
kind: Task
|
|
metadata:
|
|
name: maidn-node-static-image
|
|
namespace: tekton-pipelines
|
|
annotations:
|
|
# MaidnCLI's generated Pipeline invokes this as task `build-and-push`.
|
|
maidn.io/maidncli-pipeline-task: build-and-push
|
|
# Required params: url, revision, image, output-directory, build-configuration.
|
|
# Optional params: base-image, target-directory. Required workspace: artifacts.
|
|
maidn.io/contract: params=url,revision,image,output-directory,build-configuration[,base-image,target-directory];workspace=artifacts
|
|
spec:
|
|
stepTemplate:
|
|
env:
|
|
- name: HOME
|
|
value: /tekton/home
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1000
|
|
runAsGroup: 1000
|
|
allowPrivilegeEscalation: false
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
params:
|
|
- name: url
|
|
type: string
|
|
- name: revision
|
|
type: string
|
|
- name: image
|
|
type: string
|
|
- name: output-directory
|
|
type: string
|
|
- name: build-configuration
|
|
type: string
|
|
default: ci
|
|
- name: base-image
|
|
type: string
|
|
default: nginx:1.27-alpine
|
|
- name: target-directory
|
|
type: string
|
|
default: /www/target
|
|
workspaces:
|
|
# Persistent artifact workspace: this Task writes only layer.tar here.
|
|
- name: artifacts
|
|
volumes:
|
|
- name: local-source
|
|
emptyDir: {}
|
|
# Do not attach this annotated Secret to the TaskRun service account: Tekton
|
|
# would otherwise initialize it for every step instead of clone only.
|
|
- name: forgejo-git-credentials
|
|
secret:
|
|
secretName: forgejo-git-credentials
|
|
- name: registry-credentials
|
|
secret:
|
|
secretName: forgejo-registry-credentials
|
|
items:
|
|
- key: .dockerconfigjson
|
|
path: config.json
|
|
steps:
|
|
- name: clone
|
|
image: alpine/git:2.47.2
|
|
env:
|
|
- name: REPOSITORY_URL
|
|
value: $(params.url)
|
|
- name: REVISION
|
|
value: $(params.revision)
|
|
- name: SOURCE_PATH
|
|
value: /workspace/local-source
|
|
- name: GIT_CREDENTIALS_PATH
|
|
value: /var/run/secrets/forgejo-git-credentials
|
|
volumeMounts:
|
|
- name: local-source
|
|
mountPath: /workspace/local-source
|
|
- name: forgejo-git-credentials
|
|
mountPath: /var/run/secrets/forgejo-git-credentials
|
|
readOnly: true
|
|
script: |
|
|
#!/bin/sh
|
|
set -eu
|
|
case "$REPOSITORY_URL" in https://git.pingu.pw/*) ;; *) exit 1 ;; esac
|
|
repository_path=${REPOSITORY_URL#https://git.pingu.pw/}
|
|
case "$repository_path" in *.git) ;; *) exit 1 ;; esac
|
|
case "$repository_path" in ''|*[!A-Za-z0-9._/-]*|/*|*//*|*..*) exit 1 ;; esac
|
|
case "$REVISION" in [A-Za-z0-9]*) ;; *) exit 1 ;; esac
|
|
case "$REVISION" in *[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac
|
|
[ -r "$GIT_CREDENTIALS_PATH/username" ] && [ -r "$GIT_CREDENTIALS_PATH/password" ] || exit 1
|
|
cat > /tmp/git-askpass <<'EOF'
|
|
#!/bin/sh
|
|
case "$1" in
|
|
*Username*) cat "$GIT_CREDENTIALS_PATH/username" ;;
|
|
*Password*) cat "$GIT_CREDENTIALS_PATH/password" ;;
|
|
*) exit 1 ;;
|
|
esac
|
|
EOF
|
|
chmod 700 /tmp/git-askpass
|
|
trap 'rm -f /tmp/git-askpass' EXIT
|
|
GIT_ASKPASS=/tmp/git-askpass GIT_TERMINAL_PROMPT=0 git clone "$REPOSITORY_URL" "$SOURCE_PATH"
|
|
git -c safe.directory="$SOURCE_PATH" -C "$SOURCE_PATH" checkout "$REVISION"
|
|
- name: build-layer
|
|
image: node:22-alpine
|
|
env:
|
|
- name: OUTPUT_DIRECTORY
|
|
value: $(params.output-directory)
|
|
- name: SOURCE_PATH
|
|
value: /workspace/local-source
|
|
- name: ARTIFACT_PATH
|
|
value: $(workspaces.artifacts.path)
|
|
- name: TARGET_DIRECTORY
|
|
value: $(params.target-directory)
|
|
- name: BUILD_CONFIGURATION
|
|
value: $(params.build-configuration)
|
|
- name: NODE_OPTIONS
|
|
value: --max-old-space-size=384
|
|
volumeMounts:
|
|
- name: local-source
|
|
mountPath: /workspace/local-source
|
|
resources:
|
|
requests:
|
|
memory: 256Mi
|
|
limits:
|
|
memory: 512Mi
|
|
script: |
|
|
#!/bin/sh
|
|
set -eu
|
|
case "$OUTPUT_DIRECTORY" in ''|/*|-*|*[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac
|
|
case "$TARGET_DIRECTORY" in /*) ;; *) exit 1 ;; esac
|
|
target_path=${TARGET_DIRECTORY#/}
|
|
case "$target_path" in ''|-*|*[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac
|
|
case "$BUILD_CONFIGURATION" in ''|-*|*[!A-Za-z0-9._-]*) exit 1 ;; esac
|
|
build_dir=$(mktemp -d)
|
|
layer_dir=$(mktemp -d)
|
|
trap 'rm -rf "$build_dir" "$layer_dir"' EXIT
|
|
cp -R "$SOURCE_PATH"/. "$build_dir"
|
|
cd "$build_dir"
|
|
# ponytail: no lockfile; skip install scripts and use npm ci when package-lock.json is committed.
|
|
npm install --ignore-scripts --no-audit --no-fund --package-lock=false
|
|
npm run build -- --configuration "$BUILD_CONFIGURATION"
|
|
test -d "$OUTPUT_DIRECTORY"
|
|
mkdir -p "$layer_dir/$target_path"
|
|
cp -R "$OUTPUT_DIRECTORY"/. "$layer_dir/$target_path/"
|
|
tar -C "$layer_dir" -cf "$ARTIFACT_PATH/layer.tar" "$target_path"
|
|
for memory_peak_path in /sys/fs/cgroup/memory.peak /sys/fs/cgroup/memory/memory.max_usage_in_bytes; do
|
|
if [ -r "$memory_peak_path" ] && memory_peak=$(cat "$memory_peak_path"); then
|
|
case "$memory_peak" in ''|*[!0-9]*) ;; *) printf 'cgroup memory peak: %s\n' "$memory_peak"; break ;; esac
|
|
fi
|
|
done
|
|
- name: validate-push-inputs
|
|
image: alpine:3.21.3
|
|
env:
|
|
- name: IMAGE
|
|
value: $(params.image)
|
|
- name: REVISION
|
|
value: $(params.revision)
|
|
- name: BASE_IMAGE
|
|
value: $(params.base-image)
|
|
script: |
|
|
#!/bin/sh
|
|
set -eu
|
|
case "$IMAGE" in git.pingu.pw/*) ;; *) exit 1 ;; esac
|
|
image_path=${IMAGE#git.pingu.pw/}
|
|
case "$image_path" in ''|*[!A-Za-z0-9._/-]*|/*|*//*|*..*|*/) exit 1 ;; esac
|
|
case "$REVISION" in [A-Za-z0-9]*) ;; *) exit 1 ;; esac
|
|
case "$REVISION" in *[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac
|
|
case "$BASE_IMAGE" in ''|-*|*[!A-Za-z0-9._/@:-]*|/*|*//*|*..*) exit 1 ;; esac
|
|
- name: push
|
|
image: gcr.io/go-containerregistry/crane:v0.21.7
|
|
args:
|
|
- append
|
|
- --base=$(params.base-image)
|
|
- --new_layer=$(workspaces.artifacts.path)/layer.tar
|
|
- --new_tag=$(params.image):$(params.revision)
|
|
volumeMounts:
|
|
- name: registry-credentials
|
|
mountPath: /tekton/home/.docker
|