devcontainer: Add the GitLab CLI and glab-axi

Install `glab`, the GitLab CLI, and `glab-axi`, an agent-ergonomic
wrapper around it, in the development container.

Default `GITLAB_HOST` to `gitlab.kitware.com` so that both address our
GitLab instance without further configuration, persist the `glab`
configuration directory on a volume so that a credential need be created
only once, and pass a `GITLAB_TOKEN` or `GITLAB_CLIENT_ID` from the host
through to the container.

Neither tool can authenticate on its own, so check for a working
credential each time a tool attaches to the container and print what
remains to be set up if there is none.
This commit is contained in:
Taylor Braun-Jones
2026-09-08 16:23:53 +00:00
parent d326c8afd5
commit 69c15636b6
5 changed files with 125 additions and 2 deletions
+9
View File
@@ -31,6 +31,15 @@ RUN --mount=type=bind,source=install_deps.sh,target=/root/install_deps.sh \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
sh /root/install_deps.sh
# Install the GitLab CLI, `glab`, and `glab-axi`, an agent-ergonomic wrapper
# around it, for interacting with our GitLab instance. Keep the packages
# `npm` downloads in a cache, and unpack the `glab` release in a `tmpfs`, so
# that neither leaves anything behind in the image.
RUN --mount=type=bind,source=install_glab.sh,target=/root/install_glab.sh \
--mount=type=cache,target=/root/.npm,sharing=locked \
--mount=type=tmpfs,target=/tmp \
sh /root/install_glab.sh
# Create an unprivileged user matching the typical host account so that files
# created in the mounted source tree are not owned by `root`.
RUN --mount=type=bind,source=create_user.sh,target=/root/create_user.sh \
+12
View File
@@ -4,11 +4,23 @@
"dockerfile": "Dockerfile"
},
"remoteUser": "cmake-dev",
"containerEnv": {
"GITLAB_HOST": "gitlab.kitware.com"
},
"remoteEnv": {
"GITLAB_CLIENT_ID": "${localEnv:GITLAB_CLIENT_ID}",
"GITLAB_TOKEN": "${localEnv:GITLAB_TOKEN}"
},
"mounts": [
{
"type": "volume",
"source": "cmake-dev-ccache",
"target": "/home/cmake-dev/.cache/ccache"
},
{
"type": "volume",
"source": "cmake-dev-glab-cli",
"target": "/home/cmake-dev/.config/glab-cli"
}
],
"postAttachCommand": "${containerWorkspaceFolder}/.devcontainer/setup-status.sh",
+43
View File
@@ -0,0 +1,43 @@
#!/bin/sh
# Install the GitLab CLI, `glab`, and `glab-axi`, an agent-ergonomic wrapper
# around it. Neither is provided by the distribution.
# See `Help/dev/devcontainer.rst`.
set -e
readonly glab_version="1.114.0"
readonly glab_axi_version="0.6.0"
case "$(uname -m)" in
x86_64)
arch="amd64"
sha256sum="00e892a80d586a1e8b8fdc035321923db99dce0caa3b0c4fd72c5337ffdb1c48"
;;
aarch64)
arch="arm64"
sha256sum="d34d7ddb96ce5e5f3423d7e8053cb14c36bd93984e4b96320f7e20a341b83498"
;;
*)
echo "Unsupported architecture: $(uname -m)" >&2
exit 1
;;
esac
readonly filename="glab_${glab_version}_linux_${arch}.tar.gz"
readonly baseurl="https://gitlab.com/gitlab-org/cli/-/releases/v${glab_version}/downloads"
cd /tmp
curl -L -o "$filename" "$baseurl/$filename"
echo "$sha256sum $filename" > glab.sha256sum
sha256sum --check glab.sha256sum
tar -C /usr/local -xzf "$filename" bin/glab
rm "$filename" glab.sha256sum
# Enable shell completion for interactive use.
mkdir -p /etc/bash_completion.d
/usr/local/bin/glab completion --shell bash > /etc/bash_completion.d/glab
# `glab-axi` is distributed only through npm. Its command surface is
# documented at https://axi.md.
npm install --global --no-audit --no-fund "glab-axi@${glab_axi_version}"
+35 -2
View File
@@ -20,6 +20,39 @@ Run 'Utilities/SetupForDevelopment.sh' to configure your Git identity and
install the project's commit hooks. The work tree is shared with the host,
so running it here sets up both.
MESSAGE
else
echo "git: this work tree is set up for development."
fi
readonly host="${GITLAB_HOST:-gitlab.com}"
if glab auth status --hostname "$host" > /dev/null 2>&1; then
exit 0
fi
# The OAuth flows need the application ID of an OAuth application registered
# on the instance. Offer them only when one is available, and prefer the
# device flow because it needs no redirect back into the container.
if test -n "${GITLAB_CLIENT_ID:-}"; then
readonly login="glab auth login --hostname $host --device"
readonly hint=""
else
readonly login="glab auth login --hostname $host"
readonly hint="
Setting GITLAB_CLIENT_ID, on the host, to the application ID of a GitLab
OAuth application offers to sign in through that application instead.
"
fi
cat <<MESSAGE
glab: no credential for $host yet.
Set one up in either of two ways:
* Run this in the container, which stores the credential under
~/.config/glab-cli, on a volume that persists across rebuilds:
$login
* Or set GITLAB_TOKEN, on the host, to a GitLab personal access token
before starting the container. It is passed through automatically.
$hint
Run '.devcontainer/setup-status.sh' here in the container to check again.
MESSAGE
+26
View File
@@ -128,16 +128,42 @@ against, the container provides:
* ``gdb``, to debug CMake as described in the `CMake Debugging Guide`_.
* ``glab``, the `GitLab CLI`_, to work with merge requests, issues, and
pipelines on our GitLab instance, and `glab-axi`_, a wrapper around it
whose output follows the `AXI`_ conventions:
.. code-block:: console
$ glab mr list
$ glab-axi mr view 1234
See `GitLab Authentication`_ below for the one-time setup they need.
.. _`C++ Code Style`: source.rst#c-code-style
.. _`.pre-commit-config.yaml`: ../../.pre-commit-config.yaml
.. _`CMake Documentation Guide`: documentation.rst
.. _`CMake Debugging Guide`: debug.rst
.. _`GitLab CLI`: https://docs.gitlab.com/editor_extensions/gitlab_cli/
.. _`glab-axi`: https://github.com/karotkriss/glab-axi
.. _`AXI`: https://axi.md
The base image ships without documentation, but the container keeps the man
pages and other documentation of every package installed on top of it. Run
``sudo unminimize`` to restore the documentation of the packages the base
image itself provides.
GitLab Authentication
=====================
The container sets ``GITLAB_HOST`` to ``gitlab.kitware.com`` so that ``glab``
and ``glab-axi`` address our GitLab instance by default. Both still need a
credential for it. `.devcontainer/setup-status.sh`_ reports whether a
working credential has been configured and provides instructions to do so if
not. It is run automatically when attaching to the container.
A ``GITLAB_TOKEN`` or ``GITLAB_CLIENT_ID`` set on the host is passed through
to the container, so a credential configured outside it is used as-is.
Local Customization
===================