-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgen-docker
More file actions
executable file
·188 lines (160 loc) · 5.82 KB
/
gen-docker
File metadata and controls
executable file
·188 lines (160 loc) · 5.82 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/usr/bin/env bash
function configure-git-for-stack
{
cat <<"EOF"
# Configure Git
# Explicitly set user.name and user.email (for reproducibility)
git config --local user.name 'David Allsopp'
git config --local user.email 'david.allsopp@metastack.com'
# Ensure the normal merge style is in effect or rerere doesn't appear to work!
git config --local merge.conflictstyle merge
# Enable rerere with ~10 year retention of resolutions
git config --local rerere.enabled true
git config --local gc.rerereResolved 3650
# Speed up reconfiguration stage by sharing config.status
git config --local ocaml.configure-cache ..
# Necessary for some of the more complicated rebasing
git config --local merge.renameLimit 150000
EOF
}
cat > Dockerfile <<EOF
FROM ocaml/opam:ubuntu-24.04-opam AS base
RUN <<End-of-Script
sudo apt-get update -y
sudo apt-get install -y gawk autoconf2.69 vim
End-of-Script
RUN <<End-of-Script
# Global Git configuration
git config --global user.name 'David Allsopp'
git config --global user.email 'david.allsopp@metastack.com'
git config --global protocol.file.allow always
# Clone relocatable
git clone https://github.com/dra27/relocatable.git
# Clone ocaml
cd relocatable
git submodule update --init ocaml
cd ocaml
git remote add --fetch upstream https://github.com/ocaml/ocaml.git
$(configure-git-for-stack)
# Set-up the pre-commit githook
# Require ocaml/ocaml#14050
git show origin/pre-commit:tools/pre-commit-githook \
| sed -e '/If any/iexit \$STATUS' \
> ../.git/modules/ocaml/hooks/pre-commit
chmod +x ../.git/modules/ocaml/hooks/pre-commit
git checkout relocatable-locks
End-of-Script
FROM base AS builder
RUN <<End-of-Script
git clone --shared relocatable build
cd build
git submodule init ocaml
git clone /home/opam/relocatable/ocaml --shared --no-checkout .git/modules/ocaml
mv .git/modules/ocaml/.git/* .git/modules/ocaml/
rmdir .git/modules/ocaml/.git
cp ../relocatable/.git/modules/ocaml/hooks/pre-commit .git/modules/ocaml/hooks/
git submodule update ocaml
cd ocaml
git remote set-url origin https://github.com/dra27/ocaml.git
git remote add --fetch upstream https://github.com/ocaml/ocaml.git
$(configure-git-for-stack)
End-of-Script
WORKDIR /home/opam/build/ocaml
EOF
locks=($(git -C ocaml log --format=%h --first-parent --reverse origin/relocatable-locks | tail -n +2))
function divide
{
if (( $# <= 17 )); then
for lock in "${@:2}"; do
cat >> Dockerfile <<EOF
FROM builder AS lock-$lock
RUN test -n "\$(git branch relocatable-locks --contains '$lock' 2>/dev/null)" || { git -C .. pull origin main && git fetch --multiple upstream origin && git checkout -B relocatable-locks origin/relocatable-locks ; }
RUN script --return --command '../stack $lock || { echo "STACK FAILURE"; rm -f ../.stack-state; git reset --hard HEAD; git clean -dfx &>/dev/null; }' ../log
RUN sed -i '/use_caching=/s/1/0/' ../stack
RUN script --return --append --command '../stack $lock || echo "STACK FAILURE"' ../log
RUN git gc --no-prune && sed -i -e '/worktree/d' ../.git/modules/ocaml/config
EOF
done
cat >> Dockerfile <<EOF
FROM base AS collector${1:+-}$1
EOF
for lock in "${@:2}"; do
cat >> Dockerfile <<EOF
COPY --chown=opam:opam --from=lock-$lock /home/opam/build/.git/modules/ocaml builds/$lock/.git
COPY --from=lock-$lock /home/opam/build/log logs/log-$lock
EOF
done
else
local split="$(( ($# - 1) / 2 ))"
local left=(${@:2:$split})
local right=(${@:$(($split + 2))})
divide "${1}0" "${left[@]}"
divide "${1}1" "${right[@]}"
cat >> Dockerfile <<EOF
FROM base AS collector${1:+-}$1
COPY --chown=opam:opam --from=collector-${1}0 /home/opam/builds builds
COPY --chown=opam:opam --from=collector-${1}0 /home/opam/logs logs
COPY --chown=opam:opam --from=collector-${1}1 /home/opam/builds builds
COPY --chown=opam:opam --from=collector-${1}1 /home/opam/logs logs
EOF
fi
}
divide '' "${locks[@]}"
cat >> Dockerfile <<EOF
FROM collector AS reflog
RUN <<End-of-Script
for lock in ${locks[@]}; do
cat builds/\$lock/.git/logs/HEAD
done > HEAD
End-of-Script
FROM base AS unified
COPY --chown=opam:opam --from=collector /home/opam/builds builds
COPY --chown=opam:opam --from=collector /home/opam/logs logs
COPY --from=reflog /home/opam/HEAD .
RUN cat HEAD >> relocatable/.git/modules/ocaml/logs/HEAD && rm -f HEAD
COPY <<EOF relocatable/.git/modules/ocaml/objects/info/alternates
EOF
for lock in "${locks[@]}"; do
echo "/home/opam/builds/$lock/.git/objects"
done >> Dockerfile
cat >> Dockerfile <<ZOF
EOF
WORKDIR /home/opam/relocatable/ocaml
RUN <<End-of-Script
cat >> rebuild <<"EOF"
head="\$(git -C ../../builds/${locks[0]} rev-parse --short relocatable-cache)"
for lock in ${locks[@]:1}; do
while IFS= read -r line; do
args=(\$line)
if [[ \${#args[@]} -gt 2 ]]; then
parents=("\${args[@]:3}")
head=\$(git show --no-patch --format=%B \${args[0]} | git commit-tree -p \$head \${parents[@]/#/-p } \${args[1]})
fi
done < <(git -C ../../builds/\$lock log --format='%h %t %p' --first-parent --reverse relocatable-cache)
done
git branch relocatable-cache \$head
EOF
bash rebuild
rm rebuild
End-of-Script
ZOF
for lock in ${locks[@]}; do
cat <<EOF
FROM unified AS cache-test-$lock
RUN { git merge-base --is-ancestor $lock relocatable-locks || { git fetch origin && git checkout -B relocatable-locks origin/relocatable-locks; } } && script --return --command "../stack $lock" ../log
EOF
done >> Dockerfile
cat >> Dockerfile <<"EOF"
FROM unified AS collected-logs
EOF
for lock in ${locks[@]}; do
echo "COPY --from=cache-test-$lock /home/opam/relocatable/log combined-$lock"
done >> Dockerfile
cat >> Dockerfile <<ZOF
RUN cat ${locks[@]/#/combined-} > combined
FROM unified
COPY --from=collected-logs /home/opam/relocatable/ocaml/combined ../../logs/combined
COPY <<EOF ../../all-locks
${locks[@]}
EOF
ZOF