Skip to content

Commit 4e6bc5b

Browse files
committed
✨ Add build digest to versions.json
1 parent 6d4ae77 commit 4e6bc5b

File tree

3 files changed

+75
-12
lines changed

3 files changed

+75
-12
lines changed

.github/workflows/build.yaml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ jobs:
2121
with:
2222
enable-cache: true
2323
- name: Generate build matrix
24+
id: set-matrix
2425
run: |
2526
FORCE=$(if git log --pretty=format:"%s" HEAD^..HEAD | grep -q '\[force\]'; then echo "--force"; else echo ""; fi)
2627
uv run dpn $FORCE build-matrix --event ${{ github.event_name }}
27-
id: set-matrix
28+
2829
2930
deploy:
3031
name: ${{ matrix.key }}
@@ -34,6 +35,7 @@ jobs:
3435
strategy:
3536
matrix: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }}
3637
steps:
38+
# Setup
3739
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
3840
- uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6
3941
with:
@@ -49,25 +51,47 @@ jobs:
4951
with:
5052
username: ${{ secrets.DOCKERHUB_USERNAME }}
5153
password: ${{ secrets.DOCKERHUB_TOKEN }}
54+
55+
# Build
5256
- name: Build image
5357
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6
5458
with:
5559
context: .
5660
file: dockerfiles/${{ matrix.key }}.Dockerfile
5761
load: true
5862
tags: nikolaik/python-nodejs:${{ matrix.key }}
63+
64+
# Test
5965
- name: Run smoke tests
6066
run: |
6167
docker run --rm nikolaik/python-nodejs:${{ matrix.key }} sh -c "node --version && npm --version && yarn --version && python --version && pip --version && pipenv --version && poetry --version && uv --version"
68+
69+
# Push image
6270
- name: Push image
6371
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6
72+
id: build-and-push
6473
with:
6574
context: .
6675
file: dockerfiles/${{ matrix.key }}.Dockerfile
6776
platforms: ${{ join(matrix.platforms) }}
6877
push: true
6978
tags: nikolaik/python-nodejs:${{ matrix.key }}
7079

80+
# Store build context
81+
- name: Add digest to build context
82+
run: |
83+
mkdir builds/
84+
digest="${{ steps.build-and-push.outputs.digest }}"
85+
echo '${{ toJSON(matrix) }}' | jq --arg digest "$digest" '. +={"digest": $digest}' >> "builds/${{ matrix.key }}.json"
86+
87+
- name: Upload build context
88+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
89+
with:
90+
name: build-${{ matrix.key }}
91+
path: builds/*
92+
if-no-files-found: error
93+
retention-days: 1
94+
7195
release:
7296
name: Update versions.json and README.md
7397
runs-on: ubuntu-latest
@@ -77,9 +101,17 @@ jobs:
77101
- uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6
78102
with:
79103
enable-cache: true
104+
105+
- name: Download metadata for builds
106+
uses: actions/download-artifact@v5
107+
with:
108+
path: builds
109+
pattern: build-*
110+
merge-multiple: true
111+
80112
- name: Update versions.json and README.md, then commit and push changes (if any)
81113
run: |
82-
uv run dpn --verbose release
114+
uv run dpn --verbose release --builds-dir builds/
83115
clean_checkout=$(git status --porcelain)
84116
if [[ -n "${clean_checkout}" ]]; then
85117
git config --global user.name "Nikolai Kristiansen" > /dev/null 2>&1

src/docker_python_nodejs/cli.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import argparse
22
import logging
3+
from pathlib import Path
34
from typing import Literal, cast
45

56
from .build_matrix import build_matrix
@@ -9,6 +10,7 @@
910
from .versions import (
1011
decide_version_combinations,
1112
find_new_or_updated,
13+
load_builds_metadata,
1214
persist_versions,
1315
supported_versions,
1416
)
@@ -25,6 +27,7 @@ class CLIArgs(argparse.Namespace):
2527

2628
context: str # dockerfile command arg
2729
event: str # build-matrix command arg
30+
builds_dir: Path # release command arg
2831

2932

3033
def run_dockerfile(args: CLIArgs) -> None:
@@ -39,10 +42,9 @@ def run_build_matrix(args: CLIArgs) -> None:
3942

4043

4144
def run_release(args: CLIArgs) -> None:
42-
suported_python_versions, suported_nodejs_versions = supported_versions()
43-
versions = decide_version_combinations(args.distros, suported_python_versions, suported_nodejs_versions)
45+
versions = load_builds_metadata(args.builds_dir)
4446
new_or_updated = find_new_or_updated(versions, args.force)
45-
47+
suported_python_versions, suported_nodejs_versions = supported_versions()
4648
if not new_or_updated:
4749
logger.info("No new or updated versions")
4850
return
@@ -84,9 +86,11 @@ def parse_args() -> CLIArgs:
8486
parser.add_argument("--verbose", action="store_true", help="Enable debug logging")
8587

8688
subparsers = parser.add_subparsers(dest="command", help="Sub-commands")
89+
8790
# Dockerfile command
8891
parser_dockerfile = subparsers.add_parser("dockerfile", help="Render a dockerfile based on version config")
8992
parser_dockerfile.add_argument("--context", default="", help="Dockerfile version config")
93+
9094
# Build matrix command
9195
parser_build_matrix = subparsers.add_parser("build-matrix", help="Generate CI build matrix")
9296
parser_build_matrix.add_argument(
@@ -95,6 +99,21 @@ def parse_args() -> CLIArgs:
9599
# https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
96100
help="GitHub Action event name (github.event_name)",
97101
)
102+
98103
# Release command
99-
subparsers.add_parser("release", help="Persist versions and make a release")
100-
return cast(CLIArgs, parser.parse_args())
104+
parser_release = subparsers.add_parser("release", help="Persist versions and make a release")
105+
parser_release.add_argument(
106+
"--builds-dir",
107+
type=Path,
108+
help="Builds directory with build context JSON files",
109+
)
110+
111+
cli_args = cast("CLIArgs", parser.parse_args())
112+
if cli_args.command == "release":
113+
if not cli_args.builds_dir.exists():
114+
parser.error(f"Builds directory {cli_args.builds_dir.as_posix()} does not exist")
115+
116+
if not cli_args.builds_dir.is_dir():
117+
parser.error(f"Builds directory {cli_args.builds_dir.as_posix()} is not a directory")
118+
119+
return cli_args

src/docker_python_nodejs/versions.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import logging
55
import re
66
from dataclasses import dataclass
7+
from pathlib import Path
78

89
import requests
910
from bs4 import BeautifulSoup
@@ -39,20 +40,16 @@ class LanguageVersion:
3940
canonical_version: str
4041
key: str
4142
distro: str
42-
image: str | None = None
4343

4444

4545
@dataclass
4646
class NodeJsVersion(LanguageVersion):
47-
pass
47+
image: str | None = None
4848

4949

5050
@dataclass
5151
class PythonVersion(LanguageVersion):
52-
canonical_version: str
53-
key: str
5452
image: str
55-
distro: str
5653

5754

5855
@dataclass
@@ -67,6 +64,7 @@ class BuildVersion:
6764
nodejs_canonical: str
6865
distro: str
6966
platforms: list[str]
67+
digest: str = ""
7068

7169

7270
def _is_platform_image(platform: str, image: DockerImageDict) -> bool:
@@ -286,3 +284,17 @@ def find_new_or_updated(
286284
new_or_updated.append(ver)
287285

288286
return new_or_updated
287+
288+
289+
def load_builds_metadata(builds_dir: Path) -> list[BuildVersion]:
290+
"""Traverse a directory with build context JSON files and return the corresponding BuildVersion list"""
291+
logger.info(f"Loading builds metadata from {builds_dir.as_posix()}")
292+
versions: list[BuildVersion] = []
293+
294+
for build_file in builds_dir.glob("*.json"):
295+
with build_file.open() as fp:
296+
build_data = json.load(fp)
297+
version = BuildVersion(**build_data)
298+
versions.append(version)
299+
300+
return versions

0 commit comments

Comments
 (0)