-
Notifications
You must be signed in to change notification settings - Fork 3
/
y-build
executable file
·162 lines (142 loc) · 5.97 KB
/
y-build
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env bash
[ -z "$DEBUG" ] || set -x
set -eo pipefail
# For example: --opt filename=test.Dockerfile
BUILDCTL_OPTS="$@"
FILENAME=""
for arg in $BUILDCTL_OPTS; do
case "$arg" in
--opt)
opt=true ;;
filename=*)
[ -z "$opt" ] && echo "filename arg without preceding --opt: $arg" && exit 1
FILENAME="$(echo $arg | cut -d= -f2-)"
[ -z "$FILENAME" ] && echo "Failed to extract filename from arg $arg" && exit 1
opt="" ;;
*)
opt="" ;;
esac
done
if [ -n "$FILENAME" ]; then
stat $FILENAME >/dev/null
stat $FILENAME.dockerignore >/dev/null || (echo "Missing .dockerignore for $FILENAME" && exit 1)
DOCKERFILE_SYNTAX="$(head -n 1 $FILENAME)"
fi
case "$DOCKERFILE_SYNTAX" in
"# syntax=ystack/v1-base:"*)
DOCKERFILE_BASE=$(echo $DOCKERFILE_SYNTAX | cut -d: -f2)
;;
"# syntax=docker/dockerfile:"*)
;;
*)
;;
esac
# Needed as long as we modify local files
function cleanup {
if [ -n "$DOCKERFILE_BASE" ]; then
mv $FILENAME.y-build.tmp $FILENAME
mv $FILENAME.y-build.tmp.dockerignore $FILENAME.dockerignore
rm "$DOCKERFILE_TMP.dockerignore"
fi
}
trap cleanup EXIT
if [ -n "$DOCKERFILE_BASE" ]; then
DOCKERFILE_DIR=$(dirname $FILENAME)
echo "y-stack dockerfile syntax detected base: $DOCKERFILE_BASE (in $DOCKERFILE_DIR/)"
(cd $DOCKERFILE_DIR;
stat $DOCKERFILE_BASE >/dev/null;
stat $DOCKERFILE_BASE.dockerignore >/dev/null || (echo "Missing .dockerignore for $DOCKERFILE_BASE" && exit 1)
)
head -n 1 $FILENAME.dockerignore | grep '*' >/dev/null || (echo "$FILNEAME.dockerignore must start with a * line when using a base" && exit 1)
DOCKERFILE_TMP=$(mktemp)
(cd $DOCKERFILE_DIR;
cat $DOCKERFILE_BASE > $DOCKERFILE_TMP;
echo "# ^^^ ystack base $DOCKERFILE_BASE ____ $FILENAME" >> $DOCKERFILE_TMP
cat $DOCKERFILE_BASE.dockerignore > $DOCKERFILE_TMP.dockerignore;
echo "# ^^^ ystack base $DOCKERFILE_BASE.dockerignore ____ $FILENAME.dockerignore" >> $DOCKERFILE_TMP.dockerignore
)
cat $FILENAME >> $DOCKERFILE_TMP;
cat $FILENAME.dockerignore | tail -n+2 >> $DOCKERFILE_TMP.dockerignore;
mv $FILENAME $FILENAME.y-build.tmp
mv $FILENAME.dockerignore $FILENAME.y-build.tmp.dockerignore
cat $DOCKERFILE_TMP > $FILENAME
cat $DOCKERFILE_TMP.dockerignore > $FILENAME.dockerignore
[ -z "$DEBUG" ] || ls -l $FILENAME*
[ -z "$DEBUGDEBUG" ] || cat $DOCKERFILE_TMP
[ -z "$DEBUGDEBUG" ] || cat $DOCKERFILE_TMP.dockerignore
# Default to not exporting cache when doing full builds, but add cache info to manifest
# but not if import cache is overridden because that's probably a different image URL
[ -z "$EXPORT_CACHE" ] && [ -z "$IMPORT_CACHE" ] && EXPORT_CACHE="--export-cache type=inline" && echo "Default EXPORT_CACHE changed to: $EXPORT_CACHE"
fi
# Settings
DEFAULT_REGISTRY=builds-registry.ystack.svc.cluster.local
[ -z "$BUILDS_REGISTRY" ] && BUILDS_REGISTRY=$DEFAULT_REGISTRY
[ -z "$PUSH_REGISTRY" ] && PUSH_REGISTRY=$DEFAULT_REGISTRY
[ -z "$BUILDKIT_HOST" ] && BUILDKIT_HOST=tcp://buildkitd.ystack.svc.cluster.local:8547
[ -z "$REGISTRY_PROBE_CONNECT_TIMEOUT" ] && REGISTRY_PROBE_CONNECT_TIMEOUT=3
if [ "$(curl -s --connect-timeout "$REGISTRY_PROBE_CONNECT_TIMEOUT" http://$BUILDS_REGISTRY/v2/)" != "{}" ]
then
echo "ERROR Skaffold need local access to the builds registry for digest lookup"
echo "Registry: $BUILDS_REGISTRY"
echo "Look for y-stack's ingress or port-forward utilities"
exit 1
fi
# Envs from Skaffold build custom
# (but for now we simply ignore PUSH_IMAGE as it has no clear significance for in-cluster builds)
[ -z "$BUILD_CONTEXT" ] && {
echo "No BUILD_CONTEXT env (from for example Skaffold). Using first arg like traditional Docker builds do."
BUILD_CONTEXT="$1"
[ -z "$BUILD_CONTEXT" ] && echo "... and no first arg either. Exiting." && exit 1
}
[ -z "$BUILD_CONTEXT_DOCKERFILE" ] && BUILD_CONTEXT_DOCKERFILE="$BUILD_CONTEXT" # Do these ever differ?
[ -z "$IMAGE" ] && {
name=${PWD##*/}
IMAGE="$BUILDS_REGISTRY/y-stack-temp-builds/$name"
echo "No IMAGE env (from for example Skaffold). Guessing: $IMAGE"
}
# Hooks, evaluating reliance on PATH for that
command -v y-hook-build-pre && cd $BUILD_CONTEXT && y-hook-build-pre
IMAGE=$IMAGE
case "$IMAGE" in
$BUILDS_REGISTRY/* ) ;;
$BUILDS_REGISTRY:80/* ) ;;
$PUSH_REGISTRY/* ) ;;
$PUSH_REGISTRY:80/* ) ;;
* ) echo "Output is restricted to PUSH_REGISTRY=$PUSH_REGISTRY. Got: $IMAGE" && exit 1 ;;
esac
[ -n "$SOURCE_DATE_EPOCH" ] || SOURCE_DATE_EPOCH=0
OUTPUT="type=image,name=$IMAGE,push=true"
[ "$REWRITE_TIMESTAMP" != "true" ] || OUTPUT="$OUTPUT,rewrite-timestamp=true"
[ "$SOURCE_DATE_EPOCH" != "-1" ] || SOURCE_DATE_EPOCH=""
BUILD_TAG="$(echo $IMAGE | awk -F/ '{print $NF}' | awk -F@ '{print $1}' | awk -F: '{print $2}')"
# https://github.com/Yolean/build-contract/blob/a7e1a96ccec79bf413d604c344679f7439c34b49/build-contract#L21
GIT_COMMIT=$(git rev-parse --verify --short HEAD 2>/dev/null || echo '')
if [[ ! -z "$GIT_COMMIT" ]]; then
GIT_STATUS=$(git status --untracked-files=no --porcelain=v2)
if [[ ! -z "$GIT_STATUS" ]]; then
GIT_COMMIT="$GIT_COMMIT-dirty"
fi
fi
REGISTRY_CACHE_DEFAULT=$(echo $IMAGE | sed "s|[^/]*|$BUILDS_REGISTRY/ystack-buildcache|" | sed "s/:$BUILD_TAG//")
[ -z "$BUILDKIT_CACHE" ] && BUILDKIT_CACHE="type=registry,ref=$REGISTRY_CACHE_DEFAULT"
[ -z "$IMPORT_CACHE" ] && IMPORT_CACHE="--import-cache=$BUILDKIT_CACHE"
[ -z "$EXPORT_CACHE" ] && EXPORT_CACHE="--export-cache=$BUILDKIT_CACHE,mode=max"
[ "$IMPORT_CACHE" = "false" ] && IMPORT_CACHE=""
[ "$EXPORT_CACHE" = "false" ] && EXPORT_CACHE=""
OPT_PLATFORM=""
[ -z "$PLATFORMS" ] || OPT_PLATFORM="--opt platform=$PLATFORMS"
echo "Build command:"
set -x
SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" y-buildctl \
--addr $BUILDKIT_HOST \
build \
--frontend dockerfile.v0 \
--local context="$BUILD_CONTEXT" \
--local dockerfile="$BUILD_CONTEXT_DOCKERFILE" \
$OPT_PLATFORM \
--opt build-arg:build_tag=$BUILD_TAG \
--opt build-arg:git_commit=$GIT_COMMIT \
$IMPORT_CACHE \
$EXPORT_CACHE \
$BUILDCTL_OPTS \
--output "$OUTPUT"