-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile.patch-validator
More file actions
161 lines (146 loc) · 8.41 KB
/
Copy pathDockerfile.patch-validator
File metadata and controls
161 lines (146 loc) · 8.41 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
# syntax=docker/dockerfile:1.7@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e
FROM alpine:3.24.1@sha256:79ff19e9084a00eece421b2523fb93e22d730e2c0e525905de047e848e56d95f AS node_builder
ARG NODE_VERSION=24.19.0
ARG NODE_SOURCE_SHA256=f6d95e10a0431ee1067fc6aabe9f762908b4716dd35324e1ddb4b1466b76659f
ARG OPENSSL_VERSION=3.5.8
ARG OPENSSL_SOURCE_SHA256=a8f84a39918ec6415ce765d9b429d313ba97b8143169c172e734b9514464f5b2
ARG CARES_VERSION=1.34.8
ARG CARES_SOURCE_SHA256=c222b6d681096f9444d2c4863d2c1174019e27cacca0a4a5c114d36dd7d7bf78
RUN apk add --no-cache \
binutils-gold \
coreutils \
curl \
g++ \
gcc \
libgcc \
libgcc-static \
linux-headers \
make \
perl \
python3 \
py3-setuptools \
xz
RUN set -eu; \
download_exact() { \
url="$1"; \
expected="$2"; \
output="$3"; \
timeout --signal=TERM --kill-after=30s 5m \
curl --fail --location --proto '=https' --proto-redir '=https' --tlsv1.2 \
--retry 3 \
--retry-all-errors \
--retry-delay 2 \
--retry-max-time 90 \
--connect-timeout 20 \
--max-time 180 \
--output "$output" \
"$url"; \
printf '%s %s\n' "$expected" "$output" | sha256sum --check --strict; \
}; \
download_exact \
"https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}.tar.xz" \
"$NODE_SOURCE_SHA256" \
/tmp/node.tar.xz; \
download_exact \
"https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/openssl-${OPENSSL_VERSION}.tar.gz" \
"$OPENSSL_SOURCE_SHA256" \
/tmp/openssl.tar.gz; \
download_exact \
"https://github.com/c-ares/c-ares/releases/download/v${CARES_VERSION}/c-ares-${CARES_VERSION}.tar.gz" \
"$CARES_SOURCE_SHA256" \
/tmp/cares.tar.gz
# Node's canonical c-ares updater replaces the upstream payload while retaining
# Node-owned config/GYP/GN integration. Preserve only that build glue; the
# reviewed c-ares source tree itself is replaced atomically.
RUN mkdir -p /usr/src/node /usr/src/openssl \
&& tar -xJf /tmp/node.tar.xz --strip-components=1 -C /usr/src/node \
&& tar -xzf /tmp/openssl.tar.gz --strip-components=1 -C /usr/src/openssl \
&& mkdir -p /tmp/node-cares-integration /tmp/cares-reviewed \
&& cp -R /usr/src/node/deps/cares/config /tmp/node-cares-integration/config \
&& cp /usr/src/node/deps/cares/.gitignore /tmp/node-cares-integration/.gitignore \
&& cp /usr/src/node/deps/cares/cares.gyp /tmp/node-cares-integration/cares.gyp \
&& cp /usr/src/node/deps/cares/*.gn /usr/src/node/deps/cares/*.gni /tmp/node-cares-integration/ \
&& tar -xzf /tmp/cares.tar.gz --strip-components=1 -C /tmp/cares-reviewed \
&& rm -rf /tmp/cares-reviewed/test \
&& rm -rf /tmp/cares-reviewed/config \
&& cp -R /tmp/node-cares-integration/config /tmp/cares-reviewed/config \
&& cp /tmp/node-cares-integration/.gitignore /tmp/cares-reviewed/.gitignore \
&& cp /tmp/node-cares-integration/cares.gyp /tmp/cares-reviewed/cares.gyp \
&& cp /tmp/node-cares-integration/*.gn /tmp/node-cares-integration/*.gni /tmp/cares-reviewed/ \
&& rm -rf /usr/src/node/deps/cares \
&& mv /tmp/cares-reviewed /usr/src/node/deps/cares \
&& test -f /usr/src/node/deps/cares/config/linux/ares_config.h \
&& grep -Fq "#define ARES_VERSION_STR \"${CARES_VERSION}\"" /usr/src/node/deps/cares/include/ares_version.h
WORKDIR /usr/src/openssl
RUN ./Configure linux-x86_64 \
no-shared \
no-tests \
--prefix=/opt/openssl \
--libdir=lib \
&& make -j"$(getconf _NPROCESSORS_ONLN)" \
&& make install_sw \
&& test -f /opt/openssl/include/openssl/opensslv.h \
&& test -f /opt/openssl/lib/libcrypto.a \
&& test -f /opt/openssl/lib/libssl.a \
&& grep -Fq "OPENSSL_VERSION_MAJOR 3" /opt/openssl/include/openssl/opensslv.h \
&& grep -Fq "OPENSSL_VERSION_MINOR 5" /opt/openssl/include/openssl/opensslv.h \
&& grep -Fq "OPENSSL_VERSION_PATCH 8" /opt/openssl/include/openssl/opensslv.h
ENV PATH="/opt/node/bin:${PATH}"
WORKDIR /usr/src/node
RUN ./configure \
--prefix=/opt/node \
--fully-static \
--with-intl=small-icu \
--without-corepack \
--disable-single-executable-application \
--shared-openssl \
--shared-openssl-includes=/opt/openssl/include \
--shared-openssl-libpath=/opt/openssl/lib \
&& make -j"$(getconf _NPROCESSORS_ONLN)" V= \
&& make install \
&& test "$(/opt/node/bin/node --version)" = "v${NODE_VERSION}" \
&& test "$(/opt/node/bin/npm --version)" = "11.17.0" \
&& CARES_VERSION="${CARES_VERSION}" /opt/node/bin/node --input-type=module --eval='if (process.versions.ares !== process.env.CARES_VERSION) throw new Error(`unexpected c-ares ${process.versions.ares}`)' \
&& OPENSSL_VERSION="${OPENSSL_VERSION}" /opt/node/bin/node --input-type=module --eval='if (process.versions.openssl !== process.env.OPENSSL_VERSION) throw new Error(`unexpected OpenSSL ${process.versions.openssl}`)' \
&& /opt/node/bin/node --input-type=module --eval='/\p{ID_Continue}/u.test("a")' \
&& ! readelf -l /opt/node/bin/node | grep -q 'Requesting program interpreter' \
&& ! readelf -d /opt/node/bin/node | grep -q '(NEEDED)' \
&& strip /opt/node/bin/node \
&& printf '%s\n' \
'{"name":"node","version":"24.19.0","cpe":"cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*","license":"MIT","type":"binary","architecture":"x86_64","appCpe":"cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*","system":"nodejs","vendor":"nodejs","sourceRepo":"https://github.com/nodejs/node"}' \
>/tmp/node-package-note.json \
&& objcopy \
--add-section .note.package=/tmp/node-package-note.json \
--set-section-flags .note.package=noload,readonly \
/opt/node/bin/node \
&& readelf -p .note.package /opt/node/bin/node \
| grep -Fq 'cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*' \
&& test "$(/opt/node/bin/node --version)" = "v${NODE_VERSION}" \
&& CARES_VERSION="${CARES_VERSION}" /opt/node/bin/node --input-type=module --eval='if (process.versions.ares !== process.env.CARES_VERSION) throw new Error(`unexpected c-ares ${process.versions.ares}`)' \
&& OPENSSL_VERSION="${OPENSSL_VERSION}" /opt/node/bin/node --input-type=module --eval='if (process.versions.openssl !== process.env.OPENSSL_VERSION) throw new Error(`unexpected OpenSSL ${process.versions.openssl}`)' \
&& /opt/node/bin/node --input-type=module --eval='/\p{ID_Continue}/u.test("a")' \
&& ! readelf -l /opt/node/bin/node | grep -q 'Requesting program interpreter' \
&& ! readelf -d /opt/node/bin/node | grep -q '(NEEDED)'
FROM scratch AS runtime
ARG SOURCE_REVISION
LABEL org.opencontainers.image.source="https://github.com/ContextualWisdomLab/noema" \
org.opencontainers.image.revision="${SOURCE_REVISION}" \
org.opencontainers.image.title="Noema Patch Validator" \
org.opencontainers.image.description="Credential-free exact-head text patch validation runtime" \
org.opencontainers.image.documentation="https://github.com/ContextualWisdomLab/noema/blob/main/docs/patch-validator-image.md"
ENV NAPI_RS_FORCE_WASI=error
USER 65532:65532
WORKDIR /workspace
COPY --from=node_builder --chown=65532:65532 /opt/node/bin/node /nodejs/bin/node
COPY --from=node_builder --chown=65532:65532 --chmod=0444 /usr/src/node/LICENSE /licenses/node/LICENSE
# validator_deps is a local named BuildKit context materialized from this exact
# head's lockfile by the workflow. Copying directly from the named context avoids
# an ambiguous unpinned FROM reference while keeping npm registry resolution out
# of the Docker build authority.
COPY --from=validator_deps --chown=65532:65532 /node_modules /opt/noema/node_modules
COPY --chown=65532:65532 patch-validator/entrypoint.mjs /opt/noema/entrypoint.mjs
COPY --chown=65532:65532 patch-validator/validate-patch.mjs /opt/noema/validate-patch.mjs
COPY --chown=65532:65532 patch-validator/runtime.mjs /opt/noema/runtime.mjs
COPY --chown=65532:65532 patch-validator/validator-tsconfig.json /opt/noema/validator-tsconfig.json
COPY --chown=65532:65532 patch-validator/validator-vitest.config.mjs /opt/noema/validator-vitest.config.mjs
ENTRYPOINT ["/nodejs/bin/node", "--input-type=module", "--eval", "import { runCli } from '/opt/noema/runtime.mjs'; import { runEntrypoint } from '/opt/noema/entrypoint.mjs'; process.exitCode = runEntrypoint({ runCliImpl: runCli, writeDiagnostic: (message) => process.stderr.write(message) });"]