Skip to content

Commit 4ef2200

Browse files
all changes
1 parent af9a3e7 commit 4ef2200

File tree

5 files changed

+165
-4
lines changed

5 files changed

+165
-4
lines changed

.github/docker/Dockerfile.musl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
ARG PLATFORM=arm64
2+
ARG NODE_VERSION=16.20.1
3+
4+
FROM ${PLATFORM}/node:${NODE_VERSION}-alpine AS build
5+
6+
WORKDIR /zstd
7+
COPY . .
8+
9+
RUN apk --no-cache add make g++ libc-dev curl bash python3 py3-pip vim cmake
10+
RUN npm run install:libmongocrypt
11+
RUN npm run prebuild
12+
13+
ARG RUN_TEST
14+
RUN if [ -n "$RUN_TEST" ]; then npm test ; else echo "skipping tests" ; fi
15+
16+
FROM scratch
17+
18+
COPY --from=build /zstd/prebuilds/ /

.github/scripts/libmongocrypt.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ import events from 'node:events';
88
import path from 'node:path';
99
import https from 'node:https';
1010
import stream from 'node:stream/promises';
11-
import { buildLibmongocryptDownloadUrl, getLibmongocryptPrebuildName, resolveRoot, run } from './utils.mjs';
11+
import url from 'node:url';
12+
import { buildLibmongocryptDownloadUrl, getLibmongocryptPackageName, getLibmongocryptPrebuildName, run } from './utils.mjs';
13+
14+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
15+
16+
/** Resolves to the root of this repository */
17+
function resolveRoot(...paths) {
18+
return path.resolve(__dirname, '..', '..', ...paths);
19+
}
1220

1321
async function parseArguments() {
1422
const pkg = JSON.parse(await fs.readFile(resolveRoot('package.json'), 'utf8'));

.github/scripts/utils.mjs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// @ts-check
22

3-
import { execSync } from "child_process";
43
import path from "path";
54
import url from 'node:url';
65
import { spawn } from "node:child_process";
76
import { once } from "node:events";
7+
import { execSync } from "child_process";
88

99
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
1010

@@ -86,4 +86,54 @@ export async function run(command, args = [], options = {}) {
8686
await once(proc, 'exit');
8787

8888
if (proc.exitCode != 0) throw new Error(`CRASH(${proc.exitCode}): ${commandDetails}`);
89-
}
89+
}
90+
91+
/**
92+
* @returns the libc (`musl` or `glibc`), if the platform is linux, otherwise null.
93+
*/
94+
export function getLibc() {
95+
if (process.platform !== 'linux') return null;
96+
97+
/**
98+
* executes `ldd --version`. on Alpine linux, `ldd` and `ldd --version` return exit code 1 and print the version
99+
* info to stderr, but on other platforms, `ldd --version` prints to stdout and returns exit code 0.
100+
*
101+
* So, this script works on both by return stderr if the command returns a non-zero exit code, otherwise stdout.
102+
*/
103+
function lddVersion() {
104+
try {
105+
return execSync('ldd --version', { encoding: 'utf-8' });
106+
} catch (error) {
107+
return error.stderr;
108+
}
109+
}
110+
111+
console.error({ ldd: lddVersion() });
112+
return lddVersion().includes('musl') ? 'musl' : 'glibc';
113+
}
114+
115+
/**
116+
* @returns the name of the package inside the libmognocrypt prebuild tarball for the current platform, arch and libc (if linux).
117+
*/
118+
export function getLibmongocryptPackageName() {
119+
const platformFactory = {
120+
'darwin': () => 'macos',
121+
'win32': () => 'windows-test',
122+
'linux': () => {
123+
const key = `${getLibc()}-${process.arch}`;
124+
return {
125+
['musl-x64']: 'alpine-amd64-earthly',
126+
['musl-arm64']: 'alpine-arm64-earthly',
127+
['glibc-ppc64']: 'rhel-71-ppc64el',
128+
['glibc-s390x']: 'rhel72-zseries-test',
129+
['glibc-arm64']: 'ubuntu1804-arm64',
130+
['glibc-x64']: 'rhel-70-64-bit',
131+
}[key]
132+
}
133+
}[process.platform] ?? (() => {
134+
throw new Error('unexpected platform.')
135+
});
136+
137+
return platformFactory();
138+
}
139+

.github/workflows/test.yml

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
shell: bash
3333
run: npm run test
3434

35-
container_tests:
35+
container_tests_glibc:
3636
runs-on: ubuntu-latest
3737
strategy:
3838
matrix:
@@ -71,3 +71,42 @@ jobs:
7171
--output type=local,dest=./prebuilds,platform-split=false \
7272
-f ./.github/docker/Dockerfile.glibc \
7373
.
74+
75+
76+
container_tests_musl:
77+
runs-on: ubuntu-latest
78+
strategy:
79+
matrix:
80+
linux_arch: [amd64, arm64]
81+
node: [16.20.1, 18.x, 20.x, 22.x]
82+
fail-fast: false
83+
steps:
84+
- uses: actions/checkout@v4
85+
86+
- uses: actions/setup-node@v4
87+
with:
88+
node-version: ${{ matrix.node }}
89+
90+
- name: Get Full Node.js Version
91+
id: get_nodejs_version
92+
shell: bash
93+
run: |
94+
echo "version=$(node --print 'process.version.slice(1)')" >> "$GITHUB_OUTPUT"
95+
96+
- name: Set up QEMU
97+
uses: docker/setup-qemu-action@v3
98+
99+
- name: Set up Docker Buildx
100+
uses: docker/setup-buildx-action@v3
101+
102+
- name: Run Buildx
103+
run: |
104+
docker buildx create --name builder --bootstrap --use
105+
docker --debug buildx build --progress=plain --no-cache \
106+
--platform linux/${{ matrix.linux_arch }} \
107+
--build-arg="PLATFORM=${{ matrix.linux_arch == 'arm64' && 'arm64v8' || matrix.linux_arch }}" \
108+
--build-arg="NODE_VERSION=${{ steps.get_nodejs_version.outputs.version }}" \
109+
--build-arg="RUN_TEST=true" \
110+
--output type=local,dest=./prebuilds,platform-split=false \
111+
-f ./.github/docker/Dockerfile.musl \
112+
.

etc/docker.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#! /bin/bash
2+
3+
# script to aid in local testing of linux platforms
4+
# requires a running docker instance
5+
6+
# s390x, arm64, amd64 for ubuntu
7+
# amd64 or arm64v8 for alpine
8+
LINUX_ARCH=amd64
9+
10+
# 16.20.1+, default 16.20.1
11+
NODE_VERSION=20.0.0
12+
13+
SCRIPT_DIR=$(dirname ${BASH_SOURCE:-$0})
14+
PROJECT_DIR=$SCRIPT_DIR/..
15+
16+
build_and_test_musl() {
17+
docker buildx create --name builder --bootstrap --use
18+
19+
docker --debug buildx build --load --progress=plain --no-cache \
20+
--platform linux/$LINUX_ARCH --output=type=docker \
21+
--build-arg="PLATFORM=$LINUX_ARCH" \
22+
--build-arg="NODE_VERSION=$NODE_VERSION" \
23+
--build-arg="RUN_TEST=true" \
24+
-f ./.github/docker/Dockerfile.musl -t musl-zstd-base \
25+
.
26+
}
27+
28+
build_and_test_glibc() {
29+
docker buildx create --name builder --bootstrap --use
30+
31+
UBUNTU_VERSION=$(node --print 'Number(process.argv[1].split(`.`).at(0)) > 16 ? `noble` : `bionic`' $NODE_VERSION)
32+
NODE_ARCH=$(node -p 'process.argv[1] === `amd64` && `x64` || process.argv[1]' $LINUX_ARCH)
33+
echo $UBUNTU_VERSION
34+
docker buildx build --progress=plain --no-cache \
35+
--platform linux/$LINUX_ARCH \
36+
--build-arg="NODE_ARCH=$NODE_ARCH" \
37+
--build-arg="NODE_VERSION=$NODE_VERSION" \
38+
--build-arg="UBUNTU_VERSION=$UBUNTU_VERSION" \
39+
--build-arg="RUN_TEST=true" \
40+
--output type=local,dest=./prebuilds,platform-split=false \
41+
-f ./.github/docker/Dockerfile.glibc \
42+
$PROJECT_DIR
43+
}
44+
45+
build_and_test_musl
46+
# build_and_test_glibc

0 commit comments

Comments
 (0)