mirror of
https://github.com/nikolaik/docker-python-nodejs.git
synced 2025-09-05 23:27:57 +03:00
refactor: Split CLI into sub parsers
Misc refactoring
This commit is contained in:
committed by
Nikolai Røed Kristiansen
parent
9d4f069960
commit
2dbe44771b
6
.github/workflows/build.yaml
vendored
6
.github/workflows/build.yaml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Generate build matrix
|
||||
run: |
|
||||
FORCE=$(if git log --pretty=format:"%s" HEAD^..HEAD | grep -q '\[force\]'; then echo "--force"; else echo ""; fi)
|
||||
uv run dpn --ci-matrix $FORCE --ci-event ${{ github.event_name }}
|
||||
uv run dpn $FORCE build-matrix --event ${{ github.event_name }}
|
||||
id: set-matrix
|
||||
|
||||
deploy:
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Generate Dockerfile from config
|
||||
run: uv run dpn --dockerfile-with-context '${{ toJSON(matrix) }}'
|
||||
run: uv run dpn dockerfile --context '${{ toJSON(matrix) }}'
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
enable-cache: true
|
||||
- name: Update versions.json and README.md, then commit and push changes (if any)
|
||||
run: |
|
||||
uv run dpn --verbose --release
|
||||
uv run dpn --verbose release
|
||||
clean_checkout=$(git status --porcelain)
|
||||
if [[ -n "${clean_checkout}" ]]; then
|
||||
git config --global user.name "Nikolai Kristiansen" > /dev/null 2>&1
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,10 +1,9 @@
|
||||
debug-*.Dockerfile
|
||||
.idea/
|
||||
dockerfiles/
|
||||
.circleci/config_generated.yml
|
||||
version_config.json
|
||||
__pycache__
|
||||
.coverage
|
||||
coverage.xml
|
||||
.vscode/
|
||||
htmlcov/
|
||||
tmp/
|
||||
|
||||
@@ -44,7 +44,7 @@ ignore = [
|
||||
"FBT001", # Allow boolean function args
|
||||
"FIX001" # Allow fixme's
|
||||
]
|
||||
target-version = "py311"
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
"**/test*.py" = ["S101"]
|
||||
@@ -54,6 +54,5 @@ strict = true
|
||||
disallow_any_unimported = true
|
||||
no_implicit_optional = true
|
||||
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "--disable-socket"
|
||||
|
||||
@@ -2,6 +2,7 @@ import dataclasses
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
@@ -19,11 +20,15 @@ def _github_action_set_output(key: str, value: str) -> None:
|
||||
"""Write
|
||||
https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter
|
||||
"""
|
||||
if not GITHUB_OUTPUT:
|
||||
print("GITHUB_OUTPUT not set", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
with Path(GITHUB_OUTPUT).open("a") as fp:
|
||||
fp.write(f"{key}={value}")
|
||||
|
||||
|
||||
def generate_matrix(new_or_updated: "list[BuildVersion]", ci_event: str) -> None:
|
||||
def build_matrix(new_or_updated: "list[BuildVersion]", ci_event: str) -> None:
|
||||
if not new_or_updated and ci_event == CI_EVENT_SCHEDULED:
|
||||
logger.info("\n# Scheduled run with no new or updated versions. Doing nothing.")
|
||||
return
|
||||
@@ -1,18 +1,16 @@
|
||||
import argparse
|
||||
import logging
|
||||
from typing import cast
|
||||
from typing import Literal, cast
|
||||
|
||||
from .ci_matrix import generate_matrix
|
||||
from .build_matrix import build_matrix
|
||||
from .dockerfiles import render_dockerfile_with_context
|
||||
from .readme import format_supported_versions, update_dynamic_readme
|
||||
from .readme import update_dynamic_readme
|
||||
from .settings import DISTROS
|
||||
from .versions import (
|
||||
decide_version_combinations,
|
||||
fetch_supported_nodejs_versions,
|
||||
find_new_or_updated,
|
||||
load_versions,
|
||||
persist_versions,
|
||||
scrape_supported_python_versions,
|
||||
supported_versions,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("dpn")
|
||||
@@ -21,41 +19,48 @@ logger = logging.getLogger("dpn")
|
||||
class CLIArgs(argparse.Namespace):
|
||||
dry_run: bool
|
||||
distros: list[str]
|
||||
ci_matrix: bool
|
||||
dockerfile_with_context: str
|
||||
ci_event: str
|
||||
release: bool
|
||||
force: bool
|
||||
verbose: bool
|
||||
command: Literal["dockerfile", "build-matrix", "release"]
|
||||
force: bool # build-matrix and release command arg
|
||||
|
||||
context: str # dockerfile command arg
|
||||
event: str # build-matrix command arg
|
||||
|
||||
|
||||
def run_dockerfile(args: CLIArgs) -> None:
|
||||
render_dockerfile_with_context(args.context, args.dry_run)
|
||||
|
||||
|
||||
def run_build_matrix(args: CLIArgs) -> None:
|
||||
suported_python_versions, suported_nodejs_versions = supported_versions()
|
||||
versions = decide_version_combinations(args.distros, suported_python_versions, suported_nodejs_versions)
|
||||
new_or_updated = find_new_or_updated(versions, args.force)
|
||||
build_matrix(new_or_updated, args.event)
|
||||
|
||||
|
||||
def run_release(args: CLIArgs) -> None:
|
||||
suported_python_versions, suported_nodejs_versions = supported_versions()
|
||||
versions = decide_version_combinations(args.distros, suported_python_versions, suported_nodejs_versions)
|
||||
new_or_updated = find_new_or_updated(versions, args.force)
|
||||
|
||||
if not new_or_updated:
|
||||
logger.info("No new or updated versions")
|
||||
return
|
||||
|
||||
persist_versions(versions, args.dry_run)
|
||||
update_dynamic_readme(versions, suported_python_versions, suported_nodejs_versions, args.dry_run)
|
||||
|
||||
|
||||
def main(args: CLIArgs) -> None:
|
||||
if args.dry_run:
|
||||
logger.debug("Dry run, outputing only.")
|
||||
|
||||
if args.dockerfile_with_context:
|
||||
render_dockerfile_with_context(args.dockerfile_with_context, args.dry_run)
|
||||
return
|
||||
|
||||
current_versions = load_versions()
|
||||
suported_python_versions = scrape_supported_python_versions()
|
||||
suported_nodejs_versions = fetch_supported_nodejs_versions()
|
||||
supported_versions = format_supported_versions(suported_python_versions, suported_nodejs_versions)
|
||||
logger.debug(f"Found the following supported versions:\n{supported_versions}")
|
||||
|
||||
versions = decide_version_combinations(args.distros, suported_python_versions, suported_nodejs_versions)
|
||||
new_or_updated = find_new_or_updated(current_versions, versions, args.force)
|
||||
|
||||
if args.ci_matrix:
|
||||
generate_matrix(new_or_updated, args.ci_event)
|
||||
|
||||
if not new_or_updated and not args.ci_matrix:
|
||||
logger.info("No new or updated versions")
|
||||
return
|
||||
|
||||
if args.release:
|
||||
persist_versions(versions, args.dry_run)
|
||||
update_dynamic_readme(versions, suported_python_versions, suported_nodejs_versions, args.dry_run)
|
||||
if args.command == "dockerfile":
|
||||
run_dockerfile(args)
|
||||
elif args.command == "build-matrix":
|
||||
run_build_matrix(args)
|
||||
elif args.command == "release":
|
||||
run_release(args)
|
||||
|
||||
|
||||
def parse_args() -> CLIArgs:
|
||||
@@ -75,16 +80,21 @@ def parse_args() -> CLIArgs:
|
||||
dest="dry_run",
|
||||
help="Skip persisting, README update, and pushing of builds",
|
||||
)
|
||||
parser.add_argument("--ci-matrix", action="store_true", help="Generate CI build matrix")
|
||||
parser.add_argument(
|
||||
"--ci-event",
|
||||
parser.add_argument("--force", action="store_true", help="Force build all versions (even old)")
|
||||
parser.add_argument("--verbose", action="store_true", help="Enable debug logging")
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", help="Sub-commands")
|
||||
# Dockerfile command
|
||||
parser_dockerfile = subparsers.add_parser("dockerfile", help="Render a dockerfile based on version config")
|
||||
parser_dockerfile.add_argument("context", default="", help="Dockerfile version config")
|
||||
# Build matrix command
|
||||
parser_build_matrix = subparsers.add_parser("build-matrix", help="Generate CI build matrix")
|
||||
parser_build_matrix.add_argument(
|
||||
"--event",
|
||||
default="webhook",
|
||||
# https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
|
||||
help="GitHub Action event name (github.event_name)",
|
||||
)
|
||||
parser.add_argument("--release", action="store_true", help="Persist versions and make a release")
|
||||
parser.add_argument("--dockerfile-with-context", default="", help="Render a dockerfile based on version config")
|
||||
parser.add_argument("--force", action="store_true", help="Force build all versions (even old)")
|
||||
parser.add_argument("--verbose", action="store_true", help="Enable debug logging")
|
||||
|
||||
# Release command
|
||||
subparsers.add_parser("release", help="Persist versions and make a release")
|
||||
return cast(CLIArgs, parser.parse_args())
|
||||
|
||||
@@ -67,14 +67,10 @@ def format_supported_versions(
|
||||
python_versions: "list[SupportedVersion]",
|
||||
node_versions: "list[SupportedVersion]",
|
||||
) -> str:
|
||||
headings = ["Python version", "Start", "End"]
|
||||
rows = [[ver.version, ver.start, ver.end] for ver in sorted(python_versions, key=lambda x: x.start, reverse=True)]
|
||||
python_table = _format_md_table(headings, rows)
|
||||
def _as_rows(versions: "list[SupportedVersion]") -> list[list[str]]:
|
||||
return [[ver.version, ver.start, ver.end] for ver in sorted(versions, key=lambda x: x.start, reverse=True)]
|
||||
|
||||
headings_node = ["Node.js version", "Start", "End"]
|
||||
rows_node = [
|
||||
[ver.version, ver.start, ver.end] for ver in sorted(node_versions, key=lambda x: x.start, reverse=True)
|
||||
]
|
||||
node_table = _format_md_table(headings_node, rows_node)
|
||||
python_table = _format_md_table(["Python version", "Start", "End"], _as_rows(python_versions))
|
||||
node_table = _format_md_table(["Node.js version", "Start", "End"], _as_rows(node_versions))
|
||||
|
||||
return f"{python_table}\n{node_table}"
|
||||
|
||||
@@ -9,6 +9,8 @@ import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from semver.version import Version
|
||||
|
||||
from docker_python_nodejs.readme import format_supported_versions
|
||||
|
||||
from .docker_hub import DockerImageDict, DockerTagDict, fetch_tags
|
||||
from .nodejs_versions import (
|
||||
fetch_node_releases,
|
||||
@@ -162,6 +164,14 @@ def fetch_supported_nodejs_versions() -> list[SupportedVersion]:
|
||||
return versions
|
||||
|
||||
|
||||
def supported_versions() -> tuple[list[SupportedVersion], list[SupportedVersion]]:
|
||||
suported_python_versions = scrape_supported_python_versions()
|
||||
suported_nodejs_versions = fetch_supported_nodejs_versions()
|
||||
supported_versions = format_supported_versions(suported_python_versions, suported_nodejs_versions)
|
||||
logger.debug(f"Found the following supported versions:\n{supported_versions}")
|
||||
return suported_python_versions, suported_nodejs_versions
|
||||
|
||||
|
||||
def _has_arch_files(files: list[str], distro: str) -> bool:
|
||||
if distro == "alpine":
|
||||
return {"linux-x64-musl"}.issubset(files)
|
||||
@@ -257,13 +267,13 @@ def load_versions() -> list[BuildVersion]:
|
||||
|
||||
|
||||
def find_new_or_updated(
|
||||
current_versions: list[BuildVersion],
|
||||
versions: list[BuildVersion],
|
||||
force: bool = False,
|
||||
) -> list[BuildVersion]:
|
||||
if force:
|
||||
logger.warning("Generating full build matrix because --force is set")
|
||||
|
||||
current_versions = load_versions()
|
||||
current_versions_dict = {ver.key: ver for ver in current_versions}
|
||||
versions_dict = {ver.key: ver for ver in versions}
|
||||
new_or_updated: list[BuildVersion] = []
|
||||
|
||||
Reference in New Issue
Block a user