diff --git a/.github/workflows/test-download-latest.yml b/.github/workflows/test-download-latest.yml new file mode 100644 index 000000000..8c1f61c39 --- /dev/null +++ b/.github/workflows/test-download-latest.yml @@ -0,0 +1,36 @@ +name: "Test download_latest script" +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +jobs: + smoke-tests: + name: "OS: ${{ matrix.runner }}, node@${{ matrix.node }}" + strategy: + matrix: + runner: [ubuntu, macos] + node: [24.x] + fail-fast: false + runs-on: ${{ matrix.runner }}-latest + timeout-minutes: 30 # Installing dependencies on windows can take a while + env: + npm_config_loglevel: verbose + npm_config_foreground_scripts: "true" + PUPPETEER_SKIP_DOWNLOAD: "true" + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v6 + with: + check-latest: true + node-version: ${{ matrix.node }} + + - name: Install mongosh through download_latest.sh + run: ./download_latest.sh + + - name: Run smoke tests + run: npx -y mongodb-runner -- exec -- sh -c 'env MONGOSH_SMOKE_TEST_SERVER=$MONGODB_URI ./mongosh --smokeTests' diff --git a/README.md b/README.md index dd419c24a..1a90afe80 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,15 @@ Once downloaded, you will have to extract the binary and add it to your PATH variable. For detailed instructions for each of our supported platforms, please visit [installation documentation](https://www.mongodb.com/docs/mongodb-shell/install#mdb-shell-install). +Alternatively: +- Run `npx mongosh` to run mongosh without a full installation. This is + easiest if you already have npm installed. +- Run `download_latest.sh` to download a `mongosh` binary. You can use + the following script: +```sh +curl -fsSL https://raw.githubusercontent.com/mongodb-js/mongosh/refs/heads/main/download_latest.sh | sh +``` + ## CLI Usage diff --git a/download_latest.sh b/download_latest.sh new file mode 100755 index 000000000..b133db972 --- /dev/null +++ b/download_latest.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +set -o errexit + +MONGOSH_RELEASES_URL=https://downloads.mongodb.com/compass/mongosh.json + +say() { + echo >&2 "$@" +} + +sayf() { + # shellcheck disable=SC2059 + printf >&2 "$@" +} + +show_download_link() { + say "Download mongosh manually from:" + say + sayf "\t%s\n" 'https://www.mongodb.com/try/download/shell' +} + +for tool in jq curl; do + which "$tool" >/dev/null || { + say "This script requires '$tool'." + exit 1 + } +done + +os=$(uname -o | tr '[:upper:]' '[:lower:]') +arch=$(uname -m) + +case "$os" in + *linux) + ext=tgz + os=linux + ;; + darwin) + ext=zip + ;; + *) + say "❌ This script does not support this OS ($os)." + show_download_link + + exit 1 +esac + +# normalize $arch: +case "$arch" in + amd64|x64) + arch=x86_64 + ;; + aarch64) + arch=arm64 + ;; + *) + # Use uname’s reported architecture in the jq query. +esac + +if [ "$os" = "linux" ]; then + if ldd $(which curl) | grep -q libssl.so.3 ; then + openssl_query='and .sharedOpenssl == "openssl3"' + else + openssl_query='and (has("sharedOpenssl") | not)' + fi +else + openssl_query='' +fi + +jq_query=$(cat < "$file" + say "Downloaded $ext file; extracting mongosh …" + + unzip -j "$file" '*/bin/mongosh*' + ;; + tgz) + say "Downloading & extracting from $url …" + + curl -fsSL "$url" | tar -xzf - \ + --transform "s/.*\///" \ + --wildcards "**/bin/mongosh*" \ + | sed -E 's/^.*[/]//' + + ;; + *) + say "Bad file extension: $ext" + show_download_link + exit 1 +esac + +./mongosh --build-info >/dev/null 2>&1 || { + say "❌ Downloaded mongosh is not executable." + ./mongosh --build-info + exit 1 +} + +say "✅ Success! 'mongosh' and its crypto library are now saved in this directory." diff --git a/packages/build/src/download-center/config.spec.ts b/packages/build/src/download-center/config.spec.ts index 43d70cca9..2a0f2a27c 100644 --- a/packages/build/src/download-center/config.spec.ts +++ b/packages/build/src/download-center/config.spec.ts @@ -205,6 +205,24 @@ describe('DownloadCenter config', function () { tutorial_link: 'test', }); }); + + it('the list is sorted by semver even if versions are added out of order', function () { + const getVersionConfig1x = sinon.stub().returns({ version: '1.2.2' }); + const getVersionConfig2x = sinon.stub().returns({ version: '2.0.0' }); + const existingDownloadCenterConfig = + createDownloadCenterConfig(getVersionConfig2x); + expect(existingDownloadCenterConfig.versions).to.have.lengthOf(1); + + const updatedConfig = getUpdatedDownloadCenterConfig( + existingDownloadCenterConfig, + getVersionConfig1x + ); + + expect(updatedConfig.versions).to.deep.equal([ + { version: '2.0.0' }, + { version: '1.2.2' }, + ]); + }); }); context( diff --git a/packages/build/src/download-center/config.ts b/packages/build/src/download-center/config.ts index fd6948c44..3761033e5 100644 --- a/packages/build/src/download-center/config.ts +++ b/packages/build/src/download-center/config.ts @@ -202,6 +202,7 @@ export function getUpdatedDownloadCenterConfig( currentVersions[matchingMajorVersionIdx] = versionConfig; } + // NB: download_latest.sh depends on the specific ordering of versions here. currentVersions.sort((a, b) => semver.rcompare(a.version, b.version)); return {