diff --git a/.ci/container_setup.d/README b/.ci/container_setup.d/README new file mode 100644 index 0000000..9604335 --- /dev/null +++ b/.ci/container_setup.d/README @@ -0,0 +1,7 @@ +Files in this directory of the form '-.sh' are executed in alphabetical order. +They can assume to be provided with the following environmnent variables: +* PULP_CLI_CONFIG a path to a config file for the ci container +* CONTAINER_RUNTIME the command for interacting with containers +* BASE_PATH the directory the 'run_container.sh' script lives in + +Also a running container named 'pulp-ephemeral'. diff --git a/.ci/run_container.sh b/.ci/run_container.sh index 3730ff0..f92cb48 100755 --- a/.ci/run_container.sh +++ b/.ci/run_container.sh @@ -1,14 +1,5 @@ #!/bin/sh -# This file is shared between some projects please keep all copies in sync -# Known places: -# - https://github.com/pulp/pulp-cli/blob/main/.ci/run_container.sh -# - https://github.com/pulp/pulp-cli-deb/blob/main/.ci/run_container.sh -# - https://github.com/pulp/pulp-cli-gem/blob/main/.ci/run_container.sh -# - https://github.com/pulp/pulp-cli-maven/blob/main/.ci/run_container.sh -# - https://github.com/pulp/pulp-cli-ostree/blob/main/.ci/run_container.sh -# - https://github.com/pulp/squeezer/blob/develop/tests/run_container.sh - set -eu BASEPATH="$(dirname "$(readlink -f "$0")")" @@ -25,6 +16,16 @@ then fi export CONTAINER_RUNTIME +TMPDIR="$(mktemp -d)" + +cleanup () { + "${CONTAINER_RUNTIME}" stop pulp-ephemeral && true + rm -rf "${TMPDIR}" +} + +trap cleanup EXIT +trap cleanup INT + if [ -z "${KEEP_CONTAINER:+x}" ] then RM="yes" @@ -47,12 +48,36 @@ else SELINUX="" fi; -"${CONTAINER_RUNTIME}" run ${RM:+--rm} --env S6_KEEP_ENV=1 ${PULP_API_ROOT:+--env PULP_API_ROOT} --detach --name "pulp-ephemeral" --volume "${BASEPATH}/settings:/etc/pulp${SELINUX:+:Z}" --publish "8080:80" "ghcr.io/pulp/pulp:${IMAGE_TAG}" +mkdir -p "${TMPDIR}/settings/certs" +cp "${BASEPATH}/settings/settings.py" "${TMPDIR}/settings" -# shellcheck disable=SC2064 -trap "${CONTAINER_RUNTIME} stop pulp-ephemeral" EXIT -# shellcheck disable=SC2064 -trap "${CONTAINER_RUNTIME} stop pulp-ephemeral" INT +if [ -z "${PULP_HTTPS:+x}" ] +then + PROTOCOL="http" + PORT="80" + PULP_CONTENT_ORIGIN="http://localhost:8080/" +else + PROTOCOL="https" + PORT="443" + PULP_CONTENT_ORIGIN="https://localhost:8080/" + python3 -m trustme -d "${TMPDIR}/settings/certs" + export PULP_CA_BUNDLE="${TMPDIR}/settings/certs/client.pem" + ln -fs server.pem "${TMPDIR}/settings/certs/pulp_webserver.crt" + ln -fs server.key "${TMPDIR}/settings/certs/pulp_webserver.key" +fi +export PULP_CONTENT_ORIGIN + +"${CONTAINER_RUNTIME}" \ + run ${RM:+--rm} \ + --env S6_KEEP_ENV=1 \ + ${PULP_HTTPS:+--env PULP_HTTPS} \ + ${PULP_API_ROOT:+--env PULP_API_ROOT} \ + --env PULP_CONTENT_ORIGIN \ + --detach \ + --name "pulp-ephemeral" \ + --volume "${TMPDIR}/settings:/etc/pulp${SELINUX:+:Z}" \ + --publish "8080:${PORT}" \ + "ghcr.io/pulp/pulp:${IMAGE_TAG}" echo "Wait for pulp to start." for counter in $(seq 40 -1 0) @@ -67,7 +92,7 @@ do fi sleep 3 - if curl --fail "http://localhost:8080${PULP_API_ROOT:-/pulp/}api/v3/status/" > /dev/null 2>&1 + if curl --insecure --fail "${PROTOCOL}://localhost:8080${PULP_API_ROOT:-/pulp/}api/v3/status/" > /dev/null 2>&1 then echo "SUCCESS." break @@ -75,15 +100,19 @@ do echo "." done -# show pulpcore/plugin versions we're using -curl -s "http://localhost:8080${PULP_API_ROOT:-/pulp/}api/v3/status/" | jq '.versions|map({key: .component, value: .version})|from_entries' - # Set admin password "${CONTAINER_RUNTIME}" exec "pulp-ephemeral" pulpcore-manager reset-admin-password --password password +# Create pulp config +PULP_CLI_CONFIG="${TMPDIR}/settings/certs/cli.toml" +export PULP_CLI_CONFIG +pulp config create --overwrite --location "${PULP_CLI_CONFIG}" --base-url "${PROTOCOL}://localhost:8080" ${PULP_API_ROOT:+--api-root "${PULP_API_ROOT}"} --username "admin" --password "password" +# show pulpcore/plugin versions we're using +pulp --config "${PULP_CLI_CONFIG}" --refresh-api status + if [ -d "${BASEPATH}/container_setup.d/" ] then - run-parts --regex '^[0-9]+-[-_[:alnum:]]*\.sh$' "${BASEPATH}/container_setup.d/" + run-parts --exit-on-error --regex '^[0-9]+-[-_[:alnum:]]*\.sh$' "${BASEPATH}/container_setup.d/" fi PULP_LOGGING="${CONTAINER_RUNTIME}" "$@" diff --git a/.ci/scripts/validate_commit_message.py b/.ci/scripts/validate_commit_message.py index 1fcd519..7a7f370 100644 --- a/.ci/scripts/validate_commit_message.py +++ b/.ci/scripts/validate_commit_message.py @@ -18,10 +18,14 @@ "EXPERIMENT", ] CHANGELOG_EXTS = [f".{item['directory']}" for item in PYPROJECT_TOML["tool"]["towncrier"]["type"]] +NOISSUE_MARKER = "[noissue]" sha = sys.argv[1] message = subprocess.check_output(["git", "log", "--format=%B", "-n 1", sha]).decode("utf-8") +if NOISSUE_MARKER in message: + sys.exit("Do not add '[noissue]' in the commit message.") + if any((re.match(pattern, message) for pattern in BLOCKING_REGEX)): sys.exit("This PR is not ready for consumption.") diff --git a/.ci/settings/settings.py b/.ci/settings/settings.py index 019e6c8..63661c9 100644 --- a/.ci/settings/settings.py +++ b/.ci/settings/settings.py @@ -1,3 +1,4 @@ -CONTENT_ORIGIN = "http://localhost:8080/" ALLOWED_EXPORT_PATHS = ["/tmp"] +ORPHAN_PROTECTION_TIME = 0 ANALYTICS = False +ALLOWED_CONTENT_CHECKSUMS = ["sha1", "sha256", "sha512"] diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4a15f2a..fe59d6b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,9 +4,13 @@ updates: directory: "/" schedule: interval: daily + commit-message: + prefix: "[PIP] " open-pull-requests-limit: 10 - package-ecosystem: github-actions directory: "/" schedule: - interval: daily + interval: weekly + commit-message: + prefix: "[GHA] " open-pull-requests-limit: 10 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5be6f17..1853e9a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -18,26 +18,10 @@ jobs: steps: - name: "Checkout repository" uses: "actions/checkout@v4" - - uses: "actions/cache@v4" - with: - path: "~/.cache/pip" - key: "${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/*constraints.lock', '**/setup.py', '**/pyproject.toml') }}" - restore-keys: | - ${{ runner.os }}-pip- - - - name: "Set up Python" - uses: "actions/setup-python@v5" - with: - python-version: "3.11" - - name: "Manually install from sources" - run: | - python -m pip install -e . -e ./pulp-glue-gem - echo "CODEQL_PYTHON=$(which python)" >> "$GITHUB_ENV" - name: "Initialize CodeQL" uses: "github/codeql-action/init@v3" with: languages: "python" - setup-python-dependencies: false - name: "Perform CodeQL Analysis" uses: "github/codeql-action/analyze@v3" diff --git a/.github/workflows/pr_checks.yml b/.github/workflows/pr_checks.yml index abbbd09..9078130 100644 --- a/.github/workflows/pr_checks.yml +++ b/.github/workflows/pr_checks.yml @@ -36,25 +36,24 @@ jobs: script: | const { ADD_LABELS, REMOVE_LABELS } = process.env; - const addLabels = ADD_LABELS.split(","); - const removeLabels = REMOVE_LABELS.split(","); - - for await (const labelName of removeLabels) { - try { - await github.rest.issues.removeLabel({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - name: labelName, - }); - } catch(err) { + if (REMOVE_LABELS.length) { + for await (const labelName of REMOVE_LABELS.split(",")) { + try { + await github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: labelName, + }); + } catch(err) { + } } } - for await (const labelName of addLabels) { + if (ADD_LABELS.length) { await github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - labels: [labelName], + labels: ADD_LABELS.split(","), }); } diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9bcdb20..859b1bc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,5 +53,6 @@ jobs: IMAGE_TAG: ${{ matrix.image_tag }} FROM_TAG: ${{ matrix.from_tag }} CONTAINER_FILE: ${{ matrix.container_file }} + PULP_HTTPS: ${{ matrix.pulp_https }} PULP_API_ROOT: ${{ matrix.pulp_api_root }} run: .ci/run_container.sh make test diff --git a/.gitignore b/.gitignore index 66790aa..234fb5b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ __pycache__/ build/ tests/cli.toml pytest_pulp_cli/GPG-PRIVATE-KEY-fixture-signing -/.ci/settings/certs site/ dist/ *.po~ diff --git a/lint_requirements.txt b/lint_requirements.txt index 5553290..82c4133 100644 --- a/lint_requirements.txt +++ b/lint_requirements.txt @@ -1,9 +1,9 @@ # Lint requirements black==24.4.2 -flake8==7.0.0 +flake8==7.1.0 flake8-pyproject==1.2.3 isort==5.13.2 -mypy==1.10.0 +mypy==1.10.1 shellcheck-py==0.10.0.1 # Type annotation stubs diff --git a/pyproject.toml b/pyproject.toml index f6603a6..abe1019 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ namespaces = true # This section is co-managed by the cookiecutter templates. # Changes to existing keys should be preserved. app_label = "gem" +repository = "https://github.com/pulp/pulp-cli-gem" glue = true docs = false translations = false