Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/test-download-latest.yml
Original file line number Diff line number Diff line change
@@ -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'
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

<!-- AUTOMATICALLY_INSERT_CLI_USAGE -->
Expand Down
121 changes: 121 additions & 0 deletions download_latest.sh
Original file line number Diff line number Diff line change
@@ -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 <<EOF
.versions[0].downloads[] |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't really do a semver comparison here, right? Otherwise I think that would be highly preferable.

If we leave this as-is, I'd leave a comment in

currentVersions.sort((a, b) => semver.rcompare(a.version, b.version));
about this script depending on that specific ordering

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(@addaleax added the comment since jQ is a funky—if poetic, heh—place to do things like semver sorting.)

select(
.distro == "$os" and
.arch == "$arch"
$openssl_query
) |
.archive.url
EOF
)

url=$(curl -fsSL $MONGOSH_RELEASES_URL | jq -r "$jq_query")

if [ -z "$url" ]; then
say "❓ No download found for $os on $arch."
show_download_link
exit 1
fi

case "$ext" in
zip)
file=$(mktemp)

say "Downloading $url to $file …"
#trap 'rm -f "$file"' EXIT

curl -fsSL "$url" > "$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."
18 changes: 18 additions & 0 deletions packages/build/src/download-center/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions packages/build/src/download-center/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading