diff --git a/.github/docker/Dockerfile.win b/.github/docker/Dockerfile.win new file mode 100644 index 0000000..2f0409c --- /dev/null +++ b/.github/docker/Dockerfile.win @@ -0,0 +1,23 @@ +#escape=` +FROM mcr.microsoft.com/windows/servercore:ltsc2016 + +# Set the Node.js version you want to install +ENV NODE_VERSION 16.20.1 + +# Download and install Node.js +RUN powershell -Command ` + $ErrorActionPreference = 'Stop'; ` + Invoke-WebRequest -Uri https://nodejs.org/dist/v$env:NODE_VERSION/node-v$env:NODE_VERSION-win-x64.zip -OutFile node.zip; ` + Expand-Archive -Path node.zip -DestinationPath C:\; ` + Rename-Item -Path C:\node-v$env:NODE_VERSION-win-x64 -NewName C:\nodejs; ` + Remove-Item -Force node.zip + +# Add Node.js to PATH +ENV PATH="C:\nodejs;C:\nodejs\node_modules\npm\bin;${PATH}" + +WORKDIR "C:\mongodb-client-encryption" +COPY . . + +RUN node "C:\mongodb-client-encryption\.github\scripts\libmongocrypt.mjs" + +CMD ["ping", "-i", "20", "localhost"] diff --git a/.github/scripts/build_linux.mjs b/.github/scripts/buildx.mjs similarity index 80% rename from .github/scripts/build_linux.mjs rename to .github/scripts/buildx.mjs index 45562d8..fb5f342 100644 --- a/.github/scripts/build_linux.mjs +++ b/.github/scripts/buildx.mjs @@ -13,7 +13,7 @@ function resolveRoot(...paths) { /** `xtrace` style command runner, uses spawn so that stdio is inherited */ async function run(command, args = [], options = {}) { - const commandDetails = `+ ${command} ${args.join(' ')}${options.cwd ? ` (in: ${options.cwd})` : ''}` + const commandDetails = `+ ${command} ${args.join(' ')}${options.cwd ? ` (in: ${options.cwd})` : ''}`; console.error(commandDetails); const proc = child_process.spawn(command, args, { stdio: 'inherit', @@ -37,16 +37,23 @@ async function main() { await run('docker', ['buildx', 'create', '--name', 'builder', '--bootstrap', '--use']); } + const platform = + process.platform === 'win32' ? 'windows/amd64' : 'linux/s390x,linux/arm64,linux/amd64'; + const dockerFile = + process.platform === 'win32' + ? resolveRoot('./.github/docker/Dockerfile.win') + : resolveRoot('./.github/docker/Dockerfile.glibc'); + await run('docker', [ 'buildx', 'build', // '--progress=plain', // By default buildx detects tty and does some fancy collapsing, set progress=plain for debugging '--platform', - 'linux/s390x,linux/arm64,linux/amd64', + platform, '--output', 'type=local,dest=./prebuilds,platform-split=false', '-f', - resolveRoot('./.github/docker/Dockerfile.glibc'), + dockerFile, resolveRoot('.') ]); diff --git a/.github/scripts/libmongocrypt.mjs b/.github/scripts/libmongocrypt.mjs index fb0ccd1..a5f6a54 100644 --- a/.github/scripts/libmongocrypt.mjs +++ b/.github/scripts/libmongocrypt.mjs @@ -174,7 +174,10 @@ export async function downloadLibMongoCrypt(nodeDepsRoot, { ref }) { const unzipArgs = ['-xzv', '-C', `_libmongocrypt-${ref}`, `${prebuild}/nocrypto`]; console.error(`+ tar ${unzipArgs.join(' ')}`); - const unzip = child_process.spawn('tar', unzipArgs, { stdio: ['pipe', 'inherit'], cwd: resolveRoot('.') }); + const unzip = child_process.spawn('tar', unzipArgs, { + stdio: ['pipe', 'inherit'], + cwd: resolveRoot('.') + }); const [response] = await events.once(https.get(downloadURL), 'response'); @@ -230,7 +233,15 @@ async function main() { await run('npm', ['install', '--ignore-scripts']); // The prebuild command will make both a .node file in `./build` (local and CI testing will run on current code) // it will also produce `./prebuild/xx.tgz`. prebuild has GH upload functionality. + if (process.platform === 'win32') { + await fs.writeFile(resolveRoot('.npmrc'), 'msvs_version=2017\n', 'utf8'); + } + await run('npm', ['run', 'prebuild']); + + if (process.platform === 'win32') { + await fs.rm(resolveRoot('.npmrc'), { force: true }); + } } await main(); diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17cce5a..8635870 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,46 +8,74 @@ on: name: build jobs: - builds: + macos_builds: outputs: artifact_id: ${{ steps.upload.outputs.artifact-id }} strategy: matrix: - os: [ubuntu-latest, windows-2019, macos-11, macos-latest] + os: [macos-11, macos-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - if: ${{ runner.os == 'Linux' }} - name: Set up QEMU + - name: Build ${{ matrix.os }} Prebuild + run: node .github/scripts/libmongocrypt.mjs + shell: bash + + - id: upload + name: Upload prebuild + uses: actions/upload-artifact@v4 + with: + name: build-${{ matrix.os }} + path: prebuilds/ + if-no-files-found: 'error' + retention-days: 1 + + linux_builds: + outputs: + artifact_id: ${{ steps.upload.outputs.artifact-id }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU uses: docker/setup-qemu-action@v3 - - if: ${{ runner.os == 'Linux' }} - name: Set up Docker Buildx + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - if: ${{ runner.os == 'Linux' }} - name: Build ${{ runner.os }} Prebuild - run: node .github/scripts/build_linux.mjs + - name: Run Buildx + run: node .github/scripts/buildx.mjs - - if: ${{ runner.os != 'Linux' }} - name: Setup nodejs - uses: actions/setup-node@v4 + - id: upload + name: Upload prebuild + uses: actions/upload-artifact@v4 with: - node-version: 'lts/*' - cache: 'npm' - registry-url: 'https://registry.npmjs.org' + name: build-linux + path: prebuilds/ + if-no-files-found: 'error' + retention-days: 1 - - if: ${{ runner.os != 'Linux' }} - name: Build ${{ runner.os }} Prebuild - run: node .github/scripts/libmongocrypt.mjs - shell: bash + windows_builds: + runs-on: windows-latest + outputs: + artifact_id: ${{ steps.upload.outputs.artifact-id }} + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: | + docker build -f .github/docker/Dockerfile.win --tag m:latest . + docker run -d --name m m:latest + docker cp m:C:\\mongodb-client-encryption\\prebuilds prebuilds + docker stop m + docker rm m:latest - id: upload name: Upload prebuild uses: actions/upload-artifact@v4 with: - name: build-${{ matrix.os }} + name: build-windows path: prebuilds/ if-no-files-found: 'error' retention-days: 1