Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/integration_test_app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install pipx -y
pipx ensurepath
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
pipx install tox
- name: Run integration tests (amd64)
if: matrix.arch == 'amd64'
Expand Down
2 changes: 1 addition & 1 deletion app/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

[project]
name = "github-runner-image-builder"
version = "0.14.3"
version = "0.14.4"
authors = [
{ name = "Canonical IS DevOps", email = "is-devops-team@canonical.com" },
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ function configure_system_users() {
[Service]
PAMName=su-l
EOF
# That PAM session takes PATH from /etc/environment and runs no login shell, so ~/.profile
# never adds the user-local bin dir that pipx and `pip install --user` install into.
/usr/bin/sed -i 's|^PATH="|PATH="/home/ubuntu/.local/bin:|' /etc/environment

# Create runner user as alias to ubuntu for GARM compatibility.
# GARM expects a runner user with /home/runner/actions-runner path.
Expand All @@ -213,6 +216,7 @@ EOF
# --non-unique: allow reusing ubuntu's UID (duplicate UIDs are rejected by default).
# --uid/--gid: share ubuntu's UID/GID so both users have identical file permissions.
# --no-create-home: skip creating /home/runner; runner's home is set to /home/ubuntu instead.
# --shell: jobs get SHELL from this account, and useradd defaults to /bin/sh.
if /usr/bin/getent group runner >/dev/null 2>&1; then
echo "runner group already exists; ensuring GID matches ubuntu"
/usr/sbin/groupmod --non-unique --gid "$UBUNTU_GID" runner
Expand All @@ -221,9 +225,9 @@ EOF
fi
if /usr/bin/id -u runner >/dev/null 2>&1; then
echo "runner user already exists; ensuring UID/GID/home match ubuntu"
/usr/sbin/usermod --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --home /home/ubuntu runner
/usr/sbin/usermod --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --home /home/ubuntu --shell /bin/bash runner
else
/usr/sbin/useradd --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --no-create-home --home-dir /home/ubuntu runner
/usr/sbin/useradd --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --no-create-home --home-dir /home/ubuntu --shell /bin/bash runner
fi
/usr/sbin/usermod --append --groups docker,microk8s,lxd,sudo runner
# Symlink /home/runner -> /home/ubuntu so GARM's hardcoded /home/runner/actions-runner path resolves correctly.
Expand Down
12 changes: 12 additions & 0 deletions app/tests/integration/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ class Commands:
name="check garm-agent login session drop-in",
command="grep -x PAMName=su-l /etc/systemd/system/garm-agent.service.d/login-session.conf",
),
# garm-agent.service runs the runner as `runner` in a PAM session without a login shell;
# systemd-run reproduces that environment.
Commands(
name="check runner job PATH includes user-local bin",
command="sudo systemd-run --quiet --wait --pipe -p User=runner -p PAMName=su-l "
"printenv PATH | grep -q '^/home/ubuntu/.local/bin:'",
),
Commands(
name="check runner job SHELL is bash",
command="sudo systemd-run --quiet --wait --pipe -p User=runner -p PAMName=su-l "
"printenv SHELL | grep -qx /bin/bash",
),
Commands(name="file permission to /usr/local/bin", command="ls -ld /usr/local/bin"),
Commands(
name="file permission to /usr/local/bin (create)", command="touch /usr/local/bin/test_file"
Expand Down
8 changes: 6 additions & 2 deletions app/tests/unit/test_openstack_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,9 @@ def test__generate_cloud_init_script(
[Service]
PAMName=su-l
EOF
# That PAM session takes PATH from /etc/environment and runs no login shell, so ~/.profile
# never adds the user-local bin dir that pipx and `pip install --user` install into.
/usr/bin/sed -i 's|^PATH="|PATH="/home/ubuntu/.local/bin:|' /etc/environment

# Create runner user as alias to ubuntu for GARM compatibility.
# GARM expects a runner user with /home/runner/actions-runner path.
Expand All @@ -947,6 +950,7 @@ def test__generate_cloud_init_script(
# --non-unique: allow reusing ubuntu's UID (duplicate UIDs are rejected by default).
# --uid/--gid: share ubuntu's UID/GID so both users have identical file permissions.
# --no-create-home: skip creating /home/runner; runner's home is set to /home/ubuntu instead.
# --shell: jobs get SHELL from this account, and useradd defaults to /bin/sh.
if /usr/bin/getent group runner >/dev/null 2>&1; then
echo "runner group already exists; ensuring GID matches ubuntu"
/usr/sbin/groupmod --non-unique --gid "$UBUNTU_GID" runner
Expand All @@ -955,9 +959,9 @@ def test__generate_cloud_init_script(
fi
if /usr/bin/id -u runner >/dev/null 2>&1; then
echo "runner user already exists; ensuring UID/GID/home match ubuntu"
/usr/sbin/usermod --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --home /home/ubuntu runner
/usr/sbin/usermod --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --home /home/ubuntu --shell /bin/bash runner
else
/usr/sbin/useradd --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --no-create-home --home-dir /home/ubuntu runner
/usr/sbin/useradd --non-unique --uid "$UBUNTU_UID" --gid "$UBUNTU_GID" --no-create-home --home-dir /home/ubuntu --shell /bin/bash runner
fi
/usr/sbin/usermod --append --groups docker,microk8s,lxd,sudo runner
# Symlink /home/runner -> /home/ubuntu so GARM's hardcoded /home/runner/actions-runner path resolves correctly.
Expand Down
4 changes: 4 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<!-- vale Canonical.007-Headings-sentence-case = NO -->

## [#246 Restore the login-shell PATH and SHELL for GARM runner jobs](https://github.com/canonical/github-runner-image-builder-operator/pull/246) (2026-10-09)

- Put `/home/ubuntu/.local/bin` on `PATH` and set `SHELL=/bin/bash` for jobs started by the GARM agent, as on the previous runner manager. The agent's PAM session doesn't run a login shell, so commands installed with `pipx` or `pip install --user` failed with `command not found`, and `SHELL` was `/bin/sh`.

## [#245 Run the GARM agent in a login session](https://github.com/canonical/github-runner-image-builder-operator/pull/245) (2026-10-08)

- Run the runner started by the GARM agent in a PAM login session, as the previous runner manager did with `su -`. The agent runs as a system service, so jobs had no `XDG_RUNTIME_DIR` or user D-Bus bus, and tools that keep per-user state there, such as `skopeo login`, `podman` and `buildah`, failed with `mkdir /run/containers: permission denied`.
Expand Down
Loading