Skip to content

Commit 274f816

Browse files
committed
Extract bazel feature from devcontainer feature
bazel related code is a lot and sould be isolated in a dedicated feature. It is already some code and this way the scope is better isolated.
1 parent 17dc4d6 commit 274f816

16 files changed

Lines changed: 236 additions & 174 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Ordered by importance:
9393

9494
* `src/s-core-devcontainer/` contains the sources for the Eclipse S-CORE DevContainer.
9595
It uses pre-existing [DevContainer features](https://containers.dev/implementors/features/) to provide some standard tools like Git, LLVM, and others.
96-
In addition, it uses a so-called "local" feature (cf. `src/s-core-devcontainer/.devcontainer/s-core-local`) for the remaining tools and configuration.
96+
In addition, it uses so-called "local" features (cf. `src/s-core-devcontainer/.devcontainer/s-core-local`) for the remaining tools and configuration.
9797
* `scripts/` contains scripts to build and test the container.
9898
* `.devcontainer/` contains the definition of the DevContainer for **this** repository, i.e. the "devcontainer devcontainer".
9999
There should rarely be a need to modify this.

docs/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ One has to take ones own medicin and for that reason the [S-CORE devcontainer](.
2222
│ ┌─────────────────────────────────────────────────────────────────┐ │
2323
│ │ Build S-CORE DevContainer (src/s-core-devcontainer) │ │
2424
│ │ - Dockerfile (Ubuntu base image) │ │
25-
│ │ - Pre-existing features (Git, LLVM/Clang, Rust, …) │ │
25+
│ │ - Pre-existing features (Git, LLVM/Clang, Rust, pre-commit, …) │ │
26+
│ │ - bazel feature (available at /devcontainer/features/…) │ │
2627
│ │ - S-CORE local feature (available at /devcontainer/features/…) │ │
2728
│ └─────────────────────────────────────────────────────────────────┘ │
2829
│ │ │
@@ -48,21 +49,23 @@ The container images should be able to build all of S-CORE without extra setup.
4849
This requires that the needed tools are preinstalled, but not too much either to keep container image download times in check.
4950

5051
To achieve this, a small base image [based on Ubuntu is chosen](https://github.com/docker-library/buildpack-deps/blob/master/ubuntu/noble/curl/Dockerfile).
51-
To this image, the tools needed to build S-CORE and run its tests are added - either via pre-existing devcontainer features, or our own [S-CORE feature](../src/s-core-devcontainer/.devcontainer/s-core-local/).
52+
To this image, the tools needed to build S-CORE and run its tests are added - either via pre-existing devcontainer features, or our own [S-CORE](../src/s-core-devcontainer/.devcontainer/s-core-local/) and [bazel](../src/s-core-devcontainer/.devcontainer/bazel-feature/) features.
5253
The tools also need to support typical IDE features like enabling code completion.
5354
All of these tools could have been added via a `Dockerfile` as well, but features are the mechanism to achieve composable devcontainer implementations and are preferred instead.
5455

5556
The decision whether to use a pre-existing feature or to add a tool using the S-CORE feature is based on the tradeoff between build time and maintainability.
5657
The chosen features are installed quickly, without us having to maintain them.
5758
Other tools installed via the S-CORE feature either have no corresponding feature, or their feature took so much time to install, that it was quicker done using our own code (example: Python feature).
5859

60+
Bazel and related tools have been moved into their own feature to have its setup better isolated.
61+
5962
### Proxy environments
6063

6164
To support proxy environments, environment variables are set in the [`Dockerfile`](../src/s-core-devcontainer/.devcontainer/Dockerfile) and unset if empty to not interfere with non-proxy environments.
6265

6366
## Tests
6467

65-
After an image build, tests check that each tool expected to be in the image is installed with the specified version for [pre-existing features](../src/s-core-devcontainer/test-project/test.sh) and the [S-CORE feature](../src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh).
68+
After an image build, tests check that each tool expected to be in the image is installed with the specified version for [pre-existing features](../src/s-core-devcontainer/test-project/test.sh), the [S-CORE feature](../src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh) and the [bazel feature](../src/s-core-devcontainer/.devcontainer/bazel-feature/tests/test_default.sh).
6669
This may seem overly complex at first, but prevents (1) accidentially wrong versions, (2) completely broken tools that cannot even execute.
6770
Both cases can happen and have happened in the past already, e.g. due to unexpected interactions between devcontainer features.
6871

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "Bazel and tools",
3+
"id": "bazel",
4+
"version": "1.0.0",
5+
"description": "Bazel and supplimentary tools for working with Bazel-based projects.",
6+
"dependsOn": {
7+
"./s-core-local": {} // needed for extracting versions (versions.sh)
8+
},
9+
"onCreateCommand": "/devcontainer/features/bazel/on_create_command.sh",
10+
"postCreateCommand": {
11+
// The repos in S-CORE may use different Bazel versions. This ensures that the required version is installed.
12+
// Should be removed once we provide versions of the devcontainer.
13+
"Install matching Bazel version": "bash /devcontainer/features/bazel/install_matching_bazel_version.sh"
14+
},
15+
"mounts": [
16+
{
17+
"source": "eclipse-s-core-bazel-cache",
18+
"target": "/var/cache/bazel",
19+
"type": "volume"
20+
}
21+
]
22+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Copy feature sources and tests to expected location
5+
FEATURES_DIR="/devcontainer/features"
6+
SCRIPT_PATH=$(readlink -f "$0")
7+
SCRIPT_DIR=$(dirname -- "${SCRIPT_PATH}")
8+
mkdir -p "${FEATURES_DIR}"
9+
COPY_TARGET="${FEATURES_DIR}/$(basename "${SCRIPT_DIR%%_*}")"
10+
cp -R "${SCRIPT_DIR}" "${COPY_TARGET}"
11+
rm -f "${COPY_TARGET}/devcontainer-features.env" "${COPY_TARGET}/devcontainer-features-install.sh"
12+
13+
DEBIAN_FRONTEND=noninteractive
14+
15+
# Read tool versions + metadata into environment variables
16+
. /devcontainer/features/s-core-local/versions.sh /devcontainer/features/bazel/versions.yaml
17+
18+
ARCHITECTURE=$(dpkg --print-architecture)
19+
20+
apt-get update
21+
22+
# INSTALL CONTAINER BUILD DEPENDENCIES
23+
# Container build dependencies are not pinned, since they are removed anyway after container creation.
24+
apt-get install apt-transport-https -y
25+
26+
# Bazelisk, directly from GitHub
27+
# Using the existing devcontainer feature is not optimal:
28+
# - it does not check the SHA256 checksum of the downloaded file
29+
# - it cannot pre-install a specific version of Bazel, or prepare bash completion
30+
BAZELISK_VARIANT="amd64"
31+
SHA256SUM="${bazelisk_amd64_sha256}"
32+
if [ "${ARCHITECTURE}" = "arm64" ]; then
33+
BAZELISK_VARIANT="arm64"
34+
SHA256SUM="${bazelisk_arm64_sha256}"
35+
fi
36+
curl -L "https://github.com/bazelbuild/bazelisk/releases/download/v${bazelisk_version}/bazelisk-${BAZELISK_VARIANT}.deb" -o /tmp/bazelisk.deb
37+
echo "${SHA256SUM} /tmp/bazelisk.deb" | sha256sum -c - || exit -1
38+
apt-get install -y --no-install-recommends --fix-broken /tmp/bazelisk.deb
39+
rm /tmp/bazelisk.deb
40+
41+
# Pre-install a fixed Bazel version, setup the bash command completion
42+
export USE_BAZEL_VERSION=${bazel_version}
43+
# bazelisk downloads Bazel into the home directory of the user running the command
44+
# lets assume there is only one user in the devcontainer
45+
su $(ls /home) -c "bazel help completion bash > /tmp/bazel-complete.bash"
46+
mkdir -p /etc/bash_completion.d
47+
mv /tmp/bazel-complete.bash /etc/bash_completion.d/bazel-complete.bash
48+
sh -c "echo 'INSTALLED_BAZEL_VERSION=${bazel_version}' >> /devcontainer/features/bazel/bazel_setup.sh"
49+
50+
# Configure Bazel to use system trust store for SSL/TLS connections
51+
# This is required for corporate environments with custom CA certificates
52+
echo 'startup --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit' >> /etc/bazel.bazelrc
53+
54+
# Buildifier, directly from GitHub (apparently no APT repository available)
55+
# The version is pinned to a specific release, and the SHA256 checksum is provided by the devcontainer-features.json file.
56+
BUILDIFIER_VARIANT="amd64"
57+
SHA256SUM="${buildifier_amd64_sha256}"
58+
if [ "${ARCHITECTURE}" = "arm64" ]; then
59+
BUILDIFIER_VARIANT="arm64"
60+
SHA256SUM="${buildifier_arm64_sha256}"
61+
fi
62+
curl -L "https://github.com/bazelbuild/buildtools/releases/download/v${buildifier_version}/buildifier-linux-${BUILDIFIER_VARIANT}" -o /usr/local/bin/buildifier
63+
echo "${SHA256SUM} /usr/local/bin/buildifier" | sha256sum -c - || exit -1
64+
chmod +x /usr/local/bin/buildifier
65+
66+
# Starlark Language Server, directly from GitHub (apparently no APT repository available)
67+
STARPLS_VARIANT="amd64"
68+
SHA256SUM="${starpls_amd64_sha256}"
69+
if [ "${ARCHITECTURE}" = "arm64" ]; then
70+
STARPLS_VARIANT="aarch64"
71+
SHA256SUM="${starpls_arm64_sha256}"
72+
fi
73+
curl -L "https://github.com/withered-magic/starpls/releases/download/v${starpls_version}/starpls-linux-${STARPLS_VARIANT}" -o /usr/local/bin/starpls
74+
echo "${SHA256SUM} /usr/local/bin/starpls" | sha256sum -c - || exit -1
75+
chmod +x /usr/local/bin/starpls
76+
77+
# Code completion for C++ code of Bazel projects
78+
# (see https://github.com/kiron1/bazel-compile-commands)
79+
source /etc/lsb-release
80+
curl -L "https://github.com/kiron1/bazel-compile-commands/releases/download/v${bazel_compile_commands_version}/bazel-compile-commands_${bazel_compile_commands_version}-${DISTRIB_CODENAME}_${ARCHITECTURE}.deb" -o /tmp/bazel-compile-commands.deb
81+
# Extract correct sha256 for current DISTRIB_CODENAME and check
82+
SHA256SUM="${bazel_compile_commands_amd64_sha256}"
83+
if [ "${ARCHITECTURE}" = "arm64" ]; then
84+
SHA256SUM="${bazel_compile_commands_arm64_sha256}"
85+
fi
86+
echo "${SHA256SUM} /tmp/bazel-compile-commands.deb" | sha256sum -c - || exit -1
87+
apt-get install -y --no-install-recommends --fix-broken /tmp/bazel-compile-commands.deb
88+
rm /tmp/bazel-compile-commands.deb
89+
90+
# Cleanup
91+
# REMOVE CONTAINER BUILD DEPENDENCIES
92+
apt-get remove --purge -y apt-transport-https
93+
apt-get autoremove -y
94+
apt-get clean
95+
rm -rf /var/lib/apt/lists/*

src/s-core-devcontainer/.devcontainer/s-core-local/install_matching_bazel_version.sh renamed to src/s-core-devcontainer/.devcontainer/bazel-feature/install_matching_bazel_version.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4-
. /devcontainer/features/s-core-local/bazel_setup.sh || true
4+
. /devcontainer/features/bazel/bazel_setup.sh || true
55

66
if [ -f .bazelversion ] && [ "$(cat .bazelversion)" != "$INSTALLED_BAZEL_VERSION" ]; then
77
# Pre-install the matching Bazel version, setup the bash command completion
@@ -15,5 +15,5 @@ if [ -f .bazelversion ] && [ "$(cat .bazelversion)" != "$INSTALLED_BAZEL_VERSION
1515

1616
bazel help completion ${bash} > /tmp/bazel-complete.bash
1717
sudo mv /tmp/bazel-complete.bash /etc/bash_completion.d/bazel-complete.bash
18-
echo "INSTALLED_BAZEL_VERSION=$USE_BAZEL_VERSION" | sudo tee /devcontainer/features/s-core-local/bazel_setup.sh
18+
echo "INSTALLED_BAZEL_VERSION=$USE_BAZEL_VERSION" | sudo tee /devcontainer/features/bazel/bazel_setup.sh
1919
fi
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Enable persistent Bazel cache
5+
#
6+
# Usually, a volume is mounted to /var/cache/bazel (see
7+
# devcontainer-feature.json). This shall be used as Bazel cache, which is then
8+
# preserved across container re-starts. Since the volume has a fixed
9+
# name ("eclipse-s-core-bazel-cache"), it is even used across all Eclipse
10+
# S-CORE DevContainer instances.
11+
if [ -d /var/cache/bazel ]; then
12+
echo "Bazel Cache: /var/cache/bazel exists. Checking ownership and configuring Bazel to use it as cache..."
13+
current_owner_group=$(stat -c "%U:%G" /var/cache/bazel)
14+
current_user_group="$(id -un):$(id -gn)"
15+
if [ "${current_owner_group}" = "${current_user_group}" ]; then
16+
echo "Bazel Cache: /var/cache/bazel is already owned by ${current_user_group}. "
17+
else
18+
echo "Bazel Cache: /var/cache/bazel is not owned by ${current_owner_group}. Setting ownership (this may take a few seconds) ..."
19+
sudo chown -R "${current_user_group}" /var/cache/bazel
20+
fi
21+
echo "Bazel Cache: Configuring Bazel to use /var/cache/bazel as cache..."
22+
echo "startup --output_user_root=/var/cache/bazel" >> ~/.bazelrc
23+
fi
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Read tool versions + metadata into environment variables
5+
. /devcontainer/features/s-core-local/versions.sh /devcontainer/features/bazel/versions.yaml
6+
7+
# Bazel-related tools
8+
## This is the bazel version preinstalled in the devcontainer.
9+
## A solid test would disable the network interface first to prevent a different version from being downloaded,
10+
## but that requires CAP_NET_ADMIN, which is not yet added.
11+
export USE_BAZEL_VERSION=${bazel_version}
12+
check "validate bazelisk is working and has the correct version" bash -c "bazelisk version | grep '${bazelisk_version}'"
13+
check "validate bazel is working and has the correct version" bash -c "bazel version | grep '${bazel_version}'"
14+
unset USE_BAZEL_VERSION
15+
16+
check "validate buildifier is working and has the correct version" bash -c "buildifier --version | grep '${buildifier_version}'"
17+
check "validate starpls is working and has the correct version" bash -c "starpls version | grep '${starpls_version}'"
18+
check "validate bazel-compile-commands is working and has the correct version" bash -c "bazel-compile-commands --version 2>&1 | grep '${bazel_compile_commands_version}'"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
bazel:
2+
# https://github.com/bazelbuild/bazel/releases -- latest version as of 2025-09-24
3+
version: 8.4.1
4+
# no need to define sha256 here, as bazel is installed via bazelisk
5+
6+
buildifier:
7+
version: 8.2.1
8+
amd64:
9+
# The following sha256sum is for the binary buildifier-linux-amd64
10+
# from the GitHub release page of buildtools
11+
# It is generated by running 'sha256sum buildifier-linux-amd64'
12+
sha256: 6ceb7b0ab7cf66fceccc56a027d21d9cc557a7f34af37d2101edb56b92fcfa1a
13+
arm64:
14+
# The following sha256sum is for the binary buildifier-linux-arm64
15+
# from the GitHub release page of buildtools
16+
# It is generated by running 'sha256sum buildifier-linux-arm64'
17+
sha256: 3baa1cf7eb41d51f462fdd1fff3a6a4d81d757275d05b2dd5f48671284e9a1a5
18+
19+
bazelisk:
20+
version: 1.27.0
21+
amd64:
22+
# The following sha256sums are for the deb package bazelisk_<version>_amd64.deb
23+
# It is generated by running 'sha256sum bazelisk_<version>_amd64.deb'
24+
sha256: d8b00ea975c823e15263c80200ac42979e17368547fbff4ab177af035badfa83
25+
arm64:
26+
# The following sha256sums are for the deb package bazelisk_<version>_arm64.deb
27+
# It is generated by running 'sha256sum bazelisk_<version>_arm64.deb'
28+
sha256: 173c5b367b485a30ce58c1d0d560b39d257a2d7a3c859c45d7d05eb61605a2a1
29+
30+
starpls:
31+
version: 0.1.22
32+
amd64:
33+
# The following sha256sum is for the binary starpls-linux-amd64
34+
# from the GitHub release page of starpls
35+
# It is generated by running 'sha256sum starpls-linux-amd64'
36+
sha256: 7c661cdde0d1c026665086d07523d825671e29056276681616bb32d0273c5eab
37+
arm64:
38+
# The following sha256sum is for the binary starpls-linux-arm64
39+
# from the GitHub release page of starpls
40+
# It is generated by running 'sha256sum starpls-linux-arm64'
41+
sha256: 55877ec4c3ff03e1d90d59c76f69a3a144b6c29688747c8ac4d77993e2eef1ad
42+
43+
bazel_compile_commands:
44+
version: 0.18.0
45+
amd64:
46+
# The following sha256sums are for the deb package bazel-compile-commands_<version>-noble_amd64.deb
47+
# It is generated by running 'sha256sum bazel-compile-commands_<version>-noble_amd64.deb'
48+
sha256: 6735ea846241497094719792ad3d4f67b1d3123048693d34fcdf7190f8c2da4e
49+
arm64:
50+
# The following sha256sums are for the deb package bazel-compile-commands_<version>-noble_arm64.deb
51+
# It is generated by running 'sha256sum bazel-compile-commands_<version>-noble_arm64.deb'
52+
sha256: d73998efa01cbd501b82ad6266642464b78ecd9fc6224a60c9cb558182d52d88

src/s-core-devcontainer/.devcontainer/devcontainer.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,17 @@
3737
"rustfmt"
3838
]
3939
},
40-
"./s-core-local": {}
40+
"./s-core-local": {},
41+
"./bazel-feature": {}
4142
},
4243
"overrideFeatureInstallOrder": [
43-
// this order makes it more convenient to develop the s-core-local feature, since it will be installed last
44+
// this order makes it more convenient to develop the local features, since they will be installed last
4445
// which means changes to it will be applied without needing to rebuild all other features
4546
"ghcr.io/devcontainers/features/common-utils",
4647
"ghcr.io/devcontainers-community/features/llvm",
4748
"ghcr.io/devcontainers/features/rust",
48-
"./s-core-local"
49+
"./s-core-local",
50+
"./bazel-feature"
4951
],
5052
"remoteUser": "vscode",
5153
"customizations": {

src/s-core-devcontainer/.devcontainer/s-core-local/devcontainer-feature.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,10 @@
1010
},
1111
"onCreateCommand": "/devcontainer/features/s-core-local/on_create_command.sh",
1212
"postCreateCommand": {
13-
// The repos in S-CORE may use different Bazel versions. This ensures that the required version is installed.
14-
// Should be removed once we provide versions of the devcontainer.
15-
"Install matching Bazel version": "bash /devcontainer/features/s-core-local/install_matching_bazel_version.sh",
1613
"Setup persistent bash history": "bash /devcontainer/features/s-core-local/setup_command_history.sh",
1714
"Enable pre-commit hooks": "bash /devcontainer/features/s-core-local/enable_pre_commit_hooks.sh"
1815
},
1916
"mounts": [
20-
{
21-
"source": "eclipse-s-core-bazel-cache",
22-
"target": "/var/cache/bazel",
23-
"type": "volume"
24-
},
2517
{
2618
"source": "eclipse-s-core-bash-history-${devcontainerId}",
2719
"target": "/commandhistory",

0 commit comments

Comments
 (0)