Skip to content

Commit 092209f

Browse files
authored
Merge pull request #122 from opensafely-core/ubuntu-pro
Add ESM support for 20.04 based python:v1
2 parents 0da0734 + 24900c2 commit 092209f

File tree

8 files changed

+63
-8
lines changed

8 files changed

+63
-8
lines changed

.github/workflows/build_and_publish.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ on:
33
workflow_dispatch:
44
push:
55
branches: [main]
6-
6+
env:
7+
UBUNTU_PRO_TOKEN: ${{ secrets.UBUNTU_PRO_TOKEN }}
78
jobs:
89
publish:
910
# note: this builds/tests all versions in serial for two reasons. Firstly we

.github/workflows/tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: Run tests
22
on:
33
pull_request:
4+
env:
5+
UBUNTU_PRO_TOKEN: ${{ secrets.UBUNTU_PRO_TOKEN }}
46
jobs:
57
version-tests:
68
runs-on: ubuntu-22.04

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
*~
22
venv
3+
.venv
34
__pycache__
5+
.env
6+
.secrets

DEVELOPERS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ just build v2
2929
just test v2
3030
```
3131

32+
## ESM Packages on 20.04 images
33+
34+
We still support the older python:v1, but it is based on Ubuntu 20.04, which
35+
has reached EOL for security upgrades. So we have enabled ESM via Ubuntu Pro for these images.
36+
37+
This means that you do need a valid `UBUNTU_PRO_TOKEN` environment variable to
38+
build these images.
39+
3240

3341
## Add a new package to existing version
3442

Dockerfile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# syntax=docker/dockerfile:1.2
1+
# syntax=docker/dockerfile:1.10
22
#################################################
33
#
44
# We need base python dependencies on both the builder and python images, so
@@ -22,7 +22,12 @@ ENV ACTION_EXEC=python MAJOR_VERSION=${MAJOR_VERSION} BASE=${BASE}
2222

2323
COPY ${MAJOR_VERSION}/dependencies.txt /opt/dependencies.txt
2424
# use space efficient utility from base image
25-
RUN /root/docker-apt-install.sh /opt/dependencies.txt
25+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
26+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
27+
--mount=type=bind,source=${MAJOR_VERSION}/dependencies.txt,target=/tmp/dependencies.txt \
28+
--mount=type=secret,id=ubuntu_pro_token,required=true \
29+
mkdir /workspace; \
30+
/root/docker-apt-install.sh /tmp/dependencies.txt
2631

2732
# now we have python, set up a venv to install packages to, for isolation from
2833
# system python libraries
@@ -42,8 +47,11 @@ FROM base-python as builder
4247
ARG MAJOR_VERSION
4348

4449
# install build time dependencies
45-
COPY ${MAJOR_VERSION}/build-dependencies.txt /opt/build-dependencies.txt
46-
RUN /root/docker-apt-install.sh /opt/build-dependencies.txt
50+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
51+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
52+
--mount=type=bind,source=${MAJOR_VERSION}/build-dependencies.txt,target=/tmp/build-dependencies.txt \
53+
--mount=type=secret,id=ubuntu_pro_token \
54+
/root/docker-apt-install.sh /tmp/build-dependencies.txt
4755

4856
COPY ${MAJOR_VERSION}/requirements.txt /opt/requirements.txt
4957
COPY ${MAJOR_VERSION}/packages.md /opt/packages.md

docker-compose.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ services:
55
build:
66
context: .
77
target: base-python
8+
secrets:
9+
- ubuntu_pro_token
810
cache_from: # should speed up the build in CI, where we have a cold cache
911
- ghcr.io/opensafely-core/base-action:${BASE}
1012
- ghcr.io/opensafely-core/python:${MAJOR_VERSION}
@@ -24,3 +26,7 @@ services:
2426
image: python:${MAJOR_VERSION}
2527
build:
2628
target: python
29+
30+
secrets:
31+
ubuntu_pro_token:
32+
file: ${UBUNTU_PRO_TOKEN_FILE:-.secrets/ubuntu_pro_token}

justfile

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
set dotenv-load := true
2+
3+
export UBUNTU_PRO_TOKEN_FILE := env_var_or_default('UBUNTU_PRO_TOKEN_FILE', justfile_directory() + "/.secrets/ubuntu_pro_token")
14
export DOCKER_BUILDKIT := "1"
25
# technically, these could differ by 1 seconds, but thats unlikely and doesn't matter
36
# human readable, used as label in docker image
@@ -6,8 +9,20 @@ export BUILD_DATE := `date +'%y-%m-%dT%H:%M:%S.%3NZ'`
69
export BUILD_NUMBER := `date +'%y%m%d%H%M%S'`
710
export REVISION := `git rev-parse --short HEAD`
811

12+
ensure-pro-token:
13+
#!/bin/bash
14+
set -euo pipefail
15+
token_file="{{ UBUNTU_PRO_TOKEN_FILE }}"
16+
if test -z "${UBUNTU_PRO_TOKEN:-}"; then
17+
echo "UBUNTU_PRO_TOKEN is required to create $token_file" >&2
18+
exit 1
19+
fi
20+
mkdir -p "$(dirname "$token_file")"
21+
umask 077
22+
printf '%s' "$UBUNTU_PRO_TOKEN" > "$token_file"
23+
924
# build docker image for version
10-
build version target="python" *args="":
25+
build version target="python" *args="": ensure-pro-token
1126
docker compose --env-file {{ version }}/env build --pull {{ args }} {{ target }}
1227

1328

@@ -29,8 +44,9 @@ render version *args:
2944

3045
# run linters
3146
check:
32-
@docker pull hadolint/hadolint:v2.12.0
33-
@docker run --rm -i hadolint/hadolint:v2.12.0 < Dockerfile
47+
@docker run --rm -i hadolint/hadolint:v2.14.0 < Dockerfile
48+
@ls scripts/*.sh | xargs docker run --rm -v "$PWD:/mnt:ro" koalaman/shellcheck:v0.11.0
49+
@docker run --rm -v "$PWD:/repo:ro" --workdir /repo rhysd/actionlint:1.7.10 -color
3450

3551

3652
# publish version (dry run by default - pass "true" to perform publish)

tests/test_packaging.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from pathlib import Path
2+
import subprocess
3+
4+
import pytest
5+
6+
os_release = Path("/etc/os-release").read_text()
7+
8+
@pytest.mark.skipif('VERSION_ID="20.04"' not in os_release, reason="20.04 only")
9+
def test_esm():
10+
output = subprocess.check_output(["dpkg-query", "-W", "-f='${Package}\t${Version}\n'", "libssl1.1"], text=True)
11+
assert "esm" in output

0 commit comments

Comments
 (0)