diff --git a/.ci/ansible/Containerfile.j2 b/.ci/ansible/Containerfile.j2 new file mode 100644 index 0000000..338ff69 --- /dev/null +++ b/.ci/ansible/Containerfile.j2 @@ -0,0 +1,48 @@ +FROM {{ ci_base | default(pulp_default_container) }} + +# Add source directories to container +{% for item in plugins %} +ADD ./{{ item.name }} ./{{ item.name }} +{% endfor %} + +# Install python packages +# S3 botocore needs to be patched to handle responses from minio during 0-byte uploads +# Hacking botocore (https://github.com/boto/botocore/pull/1990) + +RUN pip3 install +{%- if s3_test | default(false) -%} +{{ " " }}git+https://github.com/gerrod3/botocore.git@fix-100-continue +{%- endif -%} +{%- for item in plugins -%} +{{ " " }}{{ item.source }} +{%- if item.lowerbounds | default(false) -%} +{{ " " }}-c ./{{ item.name }}/lowerbounds_constraints.txt +{%- endif -%} +{%- if item.ci_requirements | default(false) -%} +{{ " " }}-r ./{{ item.name }}/ci_requirements.txt +{%- endif -%} +{%- endfor %} + +{% if pulp_env is defined and pulp_env %} +{% for key, value in pulp_env.items() %} +ENV {{ key | upper }}={{ value }} +{% endfor %} +{% endif %} + +{% if pulp_scenario_env is defined and pulp_scenario_env %} +{% for key, value in pulp_scenario_env.items() %} +ENV {{ key | upper }}={{ value }} +{% endfor %} +{% endif %} + +USER pulp:pulp +RUN PULP_STATIC_ROOT=/var/lib/operator/static/ PULP_CONTENT_ORIGIN=localhost \ + /usr/local/bin/pulpcore-manager collectstatic --clear --noinput --link +USER root:root + +{% for item in plugins %} +RUN export plugin_path="$(pip3 show {{ item.name }} | sed -n -e 's/Location: //p')/{{ item.name }}" && \ + ln $plugin_path/app/webserver_snippets/nginx.conf /etc/nginx/pulp/{{ item.name }}.conf || true +{% endfor %} + +ENTRYPOINT ["/init"] diff --git a/.ci/ansible/ansible.cfg b/.ci/ansible/ansible.cfg new file mode 100644 index 0000000..7acf1d9 --- /dev/null +++ b/.ci/ansible/ansible.cfg @@ -0,0 +1,7 @@ +[defaults] +inventory = inventory.yaml +filter_plugins = filter +retry_files_enabled = False +transport = local +nocows = 1 +stdout_callback = yaml diff --git a/.ci/ansible/build_container.yaml b/.ci/ansible/build_container.yaml new file mode 100644 index 0000000..c380b43 --- /dev/null +++ b/.ci/ansible/build_container.yaml @@ -0,0 +1,27 @@ +# Ansible playbook to create the pulp service containers image +--- +- hosts: localhost + gather_facts: false + vars_files: + - vars/main.yaml + tasks: + - name: "Generate Containerfile from template" + template: + src: Containerfile.j2 + dest: Containerfile + + - name: "Build pulp image" + # We build from the ../.. (parent dir of pulpcore git repo) Docker build + # "context" so that repos like pulp-smash are accessible to Docker + # build. So that PR branches can be used via relative paths. + # + # We default to using the docker build / podman buildah cache, for + # 1-off-builds and CI purposes (which has no cache across CI runs.) + # Run build.yaml with -e cache=false if your builds are using outdated + # layers. + command: "docker build --network host --no-cache={{ not cache | default(true) | bool }} -t {{ image.name }}:{{ image.tag }} -f {{ playbook_dir }}/Containerfile ../../.." + + - name: "Clean image cache" + docker_prune: + images : true +... diff --git a/.ci/ansible/filter/repr.py b/.ci/ansible/filter/repr.py new file mode 100644 index 0000000..8455c34 --- /dev/null +++ b/.ci/ansible/filter/repr.py @@ -0,0 +1,31 @@ +from __future__ import absolute_import, division, print_function +from packaging.version import parse as parse_version + +__metaclass__ = type + + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + + +def _repr_filter(value): + return repr(value) + + +def _canonical_semver_filter(value): + return str(parse_version(value)) + + +# ---- Ansible filters ---- +class FilterModule(object): + """Repr filter.""" + + def filters(self): + """Filter associations.""" + return { + "repr": _repr_filter, + "canonical_semver": _canonical_semver_filter, + } diff --git a/.ci/ansible/inventory.yaml b/.ci/ansible/inventory.yaml new file mode 100644 index 0000000..3b85c5f --- /dev/null +++ b/.ci/ansible/inventory.yaml @@ -0,0 +1,12 @@ +--- +all: + children: + containers: + hosts: + pulp: + pulp-fixtures: + minio: + ci-sftp: + vars: + ansible_connection: docker +... diff --git a/.ci/ansible/settings.py.j2 b/.ci/ansible/settings.py.j2 new file mode 100644 index 0000000..024df4e --- /dev/null +++ b/.ci/ansible/settings.py.j2 @@ -0,0 +1,60 @@ +CONTENT_ORIGIN = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}" +ANSIBLE_API_HOSTNAME = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}" +ANSIBLE_CONTENT_HOSTNAME = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}/pulp/content" +PRIVATE_KEY_PATH = "/etc/pulp/certs/token_private_key.pem" +PUBLIC_KEY_PATH = "/etc/pulp/certs/token_public_key.pem" +TOKEN_SERVER = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}/token/" +TOKEN_SIGNATURE_ALGORITHM = "ES256" +CACHE_ENABLED = True +REDIS_HOST = "localhost" +REDIS_PORT = 6379 +ANALYTICS = False + +{% if api_root is defined %} +API_ROOT = {{ api_root | repr }} +{% endif %} + +{% if pulp_settings %} +{% for key, value in pulp_settings.items() %} +{{ key | upper }} = {{ value | repr }} +{% endfor %} +{% endif %} + +{% if pulp_scenario_settings is defined and pulp_scenario_settings %} +{% for key, value in pulp_scenario_settings.items() %} +{{ key | upper }} = {{ value | repr }} +{% endfor %} +{% endif %} + +{% if s3_test | default(false) %} +DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" +MEDIA_ROOT = "" +AWS_ACCESS_KEY_ID = "{{ minio_access_key }}" +AWS_SECRET_ACCESS_KEY = "{{ minio_secret_key }}" +AWS_S3_REGION_NAME = "eu-central-1" +AWS_S3_ADDRESSING_STYLE = "path" +S3_USE_SIGV4 = True +AWS_S3_SIGNATURE_VERSION = "s3v4" +AWS_STORAGE_BUCKET_NAME = "pulp3" +AWS_S3_ENDPOINT_URL = "http://minio:9000" +AWS_DEFAULT_ACL = "@none None" +{% endif %} + +{% if azure_test | default(false) %} +DEFAULT_FILE_STORAGE = "storages.backends.azure_storage.AzureStorage" +MEDIA_ROOT = "" +AZURE_ACCOUNT_KEY = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" +AZURE_ACCOUNT_NAME = "devstoreaccount1" +AZURE_CONTAINER = "pulp-test" +AZURE_LOCATION = "pulp3" +AZURE_OVERWRITE_FILES = True +AZURE_URL_EXPIRATION_SECS = 120 +AZURE_CONNECTION_STRING = 'DefaultEndpointsProtocol={{ pulp_scheme }};AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint={{ pulp_scheme }}://ci-azurite:10000/devstoreaccount1;' +{% endif %} + +{% if gcp_test | default(false) %} +DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage" +MEDIA_ROOT = "" +GS_BUCKET_NAME = "gcppulp" +GS_CUSTOM_ENDPOINT = "http://ci-gcp:4443" +{% endif %} diff --git a/.ci/ansible/smash-config.json b/.ci/ansible/smash-config.json new file mode 100644 index 0000000..941122d --- /dev/null +++ b/.ci/ansible/smash-config.json @@ -0,0 +1,34 @@ +{ + "pulp": { + "auth": [ + "admin", + "password" + ], + "selinux enabled": false, + "version": "3", + "aiohttp_fixtures_origin": "127.0.0.1" + }, + "hosts": [ + { + "hostname": "pulp", + "roles": { + "api": { + "port": 443, + "scheme": "https", + "service": "nginx" + }, + "content": { + "port": 443, + "scheme": "https", + "service": "pulp_content_app" + }, + "pulp resource manager": {}, + "pulp workers": {}, + "redis": {}, + "shell": { + "transport": "local" + } + } + } + ] +} diff --git a/.ci/ansible/start_container.yaml b/.ci/ansible/start_container.yaml new file mode 100644 index 0000000..47e5221 --- /dev/null +++ b/.ci/ansible/start_container.yaml @@ -0,0 +1,109 @@ +# Ansible playbook to start the pulp service container and its supporting services +--- +- hosts: localhost + gather_facts: false + vars_files: + - vars/main.yaml + tasks: + - name: "Create Settings Directories" + file: + path: "{{ item }}" + state: directory + mode: "0755" + loop: + - settings + - ssh + - ~/.config/pulp_smash + + - name: "Generate Pulp Settings" + template: + src: settings.py.j2 + dest: settings/settings.py + + - name: "Configure pulp-smash" + copy: + src: smash-config.json + dest: ~/.config/pulp_smash/settings.json + + - name: "Setup docker networking" + docker_network: + name: pulp_ci_bridge + + - name: "Start Service Containers" + docker_container: + name: "{{ item.name }}" + image: "{{ item.image }}" + auto_remove: true + recreate: true + privileged: true + networks: + - name: pulp_ci_bridge + aliases: "{{ item.name }}" + volumes: "{{ item.volumes | default(omit) }}" + env: "{{ item.env | default(omit) }}" + command: "{{ item.command | default(omit) }}" + state: started + loop: "{{ services | default([]) }}" + + - name: "Retrieve Docker Network Info" + docker_network_info: + name: pulp_ci_bridge + register: pulp_ci_bridge_info + + - name: "Update /etc/hosts" + lineinfile: + path: /etc/hosts + regexp: "\\s{{ item.value.Name }}\\s*$" + line: "{{ item.value.IPv4Address | ipaddr('address') }}\t{{ item.value.Name }}" + loop: "{{ pulp_ci_bridge_info.network.Containers | dict2items }}" + become: true + + - name: "Create Pulp Bucket" + amazon.aws.s3_bucket: + aws_access_key: "{{ minio_access_key }}" + aws_secret_key: "{{ minio_secret_key }}" + s3_url: "http://minio:9000" + region: eu-central-1 + name: pulp3 + state: present + when: s3_test | default(false) + + - block: + - name: "Wait for Pulp" + uri: + url: "http://pulp{{ lookup('env', 'PULP_API_ROOT') | default('\/pulp\/', True) }}api/v3/status/" + follow_redirects: all + validate_certs: no + register: result + until: result.status == 200 + retries: 12 + delay: 5 + rescue: + - name: "Output pulp container log" + command: "docker logs pulp" + failed_when: true + + - name: "Check version of component being tested" + assert: + that: + - (result.json.versions | items2dict(key_name="component", value_name="version"))[item.app_label] | canonical_semver == (component_version | canonical_semver) + fail_msg: | + Component {{ item.app_label }} was expected to be installed in version {{ component_version }}. + Instead it is reported as version {{ (result.json.versions | items2dict(key_name="component", value_name="version"))[item.app_label] }}. + loop: "{{ 'plugins' | ansible.builtin.extract(lookup('ansible.builtin.file', '../../template_config.yml') | from_yaml) }}" + + - name: "Set pulp password in .netrc" + copy: + dest: "~/.netrc" + content: | + machine pulp + login admin + password password + +- hosts: pulp + gather_facts: false + tasks: + - name: "Set pulp admin password" + command: + cmd: "pulpcore-manager reset-admin-password --password password" +... diff --git a/.ci/assets/.gitkeep b/.ci/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.ci/assets/httpie/config.json b/.ci/assets/httpie/config.json new file mode 100644 index 0000000..0ed96f0 --- /dev/null +++ b/.ci/assets/httpie/config.json @@ -0,0 +1,7 @@ +{ + "default_options": [ + "--ignore-stdin", + "--pretty=format", + "--traceback" + ] +} diff --git a/.ci/assets/release_requirements.txt b/.ci/assets/release_requirements.txt new file mode 100644 index 0000000..c064e94 --- /dev/null +++ b/.ci/assets/release_requirements.txt @@ -0,0 +1,3 @@ +bump2version +gitpython +towncrier diff --git a/.ci/scripts/calc_deps_lowerbounds.py b/.ci/scripts/calc_deps_lowerbounds.py new file mode 100755 index 0000000..5014b05 --- /dev/null +++ b/.ci/scripts/calc_deps_lowerbounds.py @@ -0,0 +1,34 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +from packaging.requirements import Requirement + + +def main(): + """Calculate the lower bound of dependencies where possible.""" + with open("requirements.txt") as req_file: + for line in req_file: + try: + requirement = Requirement(line) + except ValueError: + print(line.strip()) + else: + for spec in requirement.specifier: + if spec.operator == ">=": + if requirement.name == "pulpcore": + operator = "~=" + else: + operator = "==" + min_version = str(spec)[2:] + print(f"{requirement.name}{operator}{min_version}") + break + else: + print(line.strip()) + + +if __name__ == "__main__": + main() diff --git a/.ci/scripts/check_gettext.sh b/.ci/scripts/check_gettext.sh new file mode 100755 index 0000000..094238f --- /dev/null +++ b/.ci/scripts/check_gettext.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../.. + +set -uv + +MATCHES=$(grep -n -r --include \*.py "_(f") + +if [ $? -ne 1 ]; then + printf "\nERROR: Detected mix of f-strings and gettext:\n" + echo "$MATCHES" + exit 1 +fi diff --git a/.ci/scripts/check_pulpcore_imports.sh b/.ci/scripts/check_pulpcore_imports.sh new file mode 100755 index 0000000..8e3f51d --- /dev/null +++ b/.ci/scripts/check_pulpcore_imports.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../.. + +set -uv + +# check for imports not from pulpcore.plugin. exclude tests +MATCHES=$(grep -n -r --include \*.py "from pulpcore.*import" . | grep -v "tests\|plugin") + +if [ $? -ne 1 ]; then + printf "\nERROR: Detected bad imports from pulpcore:\n" + echo "$MATCHES" + printf "\nPlugins should import from pulpcore.plugin." + exit 1 +fi diff --git a/.ci/scripts/check_release.py b/.ci/scripts/check_release.py new file mode 100755 index 0000000..ae29b42 --- /dev/null +++ b/.ci/scripts/check_release.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import argparse +import re +import os +import yaml +from tempfile import TemporaryDirectory +from packaging.version import Version +from git import Repo + +UPSTREAM_REMOTE = "https://github.com/pulp/pulp-docs.git" +DEFAULT_BRANCH = "main" +RELEASE_BRANCH_REGEX = r"^([0-9]+)\.([0-9]+)$" +Y_CHANGELOG_EXTS = [".feature", ".removal", ".deprecation"] +Z_CHANGELOG_EXTS = [".bugfix", ".doc", ".misc"] + + +def main(): + """Check which branches need a release.""" + parser = argparse.ArgumentParser() + parser.add_argument( + "--branches", + default="supported", + help="A comma separated list of branches to check for releases. Can also use keyword: " + "'supported'. Defaults to 'supported', see `supported_release_branches` in " + "`plugin_template.yml`.", + ) + opts = parser.parse_args() + + with TemporaryDirectory() as d: + # Clone from upstream to ensure we have updated branches & main + repo = Repo.clone_from(UPSTREAM_REMOTE, d, filter="blob:none") + heads = [h.split("/")[-1] for h in repo.git.ls_remote("--heads").split("\n")] + available_branches = [h for h in heads if re.search(RELEASE_BRANCH_REGEX, h)] + available_branches.sort(key=lambda ver: Version(ver)) + available_branches.append(DEFAULT_BRANCH) + + branches = opts.branches + if branches == "supported": + with open(f"{d}/template_config.yml", mode="r") as f: + tc = yaml.safe_load(f) + branches = set(tc["supported_release_branches"]) + latest_release_branch = tc["latest_release_branch"] + if latest_release_branch is not None: + branches.add(latest_release_branch) + branches.add(DEFAULT_BRANCH) + else: + branches = set(branches.split(",")) + + if diff := branches - set(available_branches): + print(f"Supplied branches contains non-existent branches! {diff}") + exit(1) + + print(f"Checking for releases on branches: {branches}") + + releases = [] + for branch in branches: + if branch != DEFAULT_BRANCH: + # Check if a Z release is needed + changes = repo.git.ls_tree("-r", "--name-only", f"origin/{branch}", "CHANGES/") + z_release = False + for change in changes.split("\n"): + # Check each changelog file to make sure everything checks out + _, ext = os.path.splitext(change) + if ext in Y_CHANGELOG_EXTS: + print( + f"Warning: A non-backported changelog ({change}) is present in the " + f"{branch} release branch!" + ) + elif ext in Z_CHANGELOG_EXTS: + z_release = True + if z_release: + # Blobless clone does not have file contents for Z branches, + # check commit message for last Z bump + git_branch = f"origin/{branch}" + next_version = None + bump_commit = repo.git.log( + "--oneline", + "--grep=Bump version", + "-n 1", + git_branch, + "--", + ".bumpversion.cfg", + ) + if bump_commit: + next_version = bump_commit.split("→ ")[-1] + # If not found - try old-commit-msg + if not next_version: + bump_commit = repo.git.log( + "--oneline", + "--grep=Bump to", + "-n 1", + git_branch, + "--", + ".bumpversion.cfg", + ) + next_version = bump_commit.split("to ")[-1] if bump_commit else None + + # You could, theoretically, be next_vers==None here - but that's always + # been true for this script. + next_version = Version(next_version) + print( + f"A Z-release is needed for {branch}, " + f"New Version: {next_version.base_version}" + ) + releases.append(next_version) + else: + # Check if a Y release is needed + changes = repo.git.ls_tree("-r", "--name-only", DEFAULT_BRANCH, "CHANGES/") + for change in changes.split("\n"): + _, ext = os.path.splitext(change) + if ext in Y_CHANGELOG_EXTS: + # We don't put Y release bumps in the commit message, check file instead + # The 'current_version' is always the next version to release + next_version = repo.git.grep( + "current_version", DEFAULT_BRANCH, "--", ".bumpversion.cfg" + ).split("=")[-1] + next_version = Version(next_version) + print( + f"A new Y-release is needed! New Version: {next_version.base_version}" + ) + releases.append(next_version) + break + + if len(releases) == 0: + print("No new releases to perform.") + + +if __name__ == "__main__": + main() diff --git a/.ci/scripts/check_requirements.py b/.ci/scripts/check_requirements.py new file mode 100755 index 0000000..6a1eedd --- /dev/null +++ b/.ci/scripts/check_requirements.py @@ -0,0 +1,66 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import warnings +from pkg_resources import Requirement + + +CHECK_MATRIX = [ + ("requirements.txt", True, True, True), + ("dev_requirements.txt", False, True, False), + ("ci_requirements.txt", False, True, True), + ("doc_requirements.txt", False, True, False), + ("lint_requirements.txt", False, True, True), + ("unittest_requirements.txt", False, True, True), + ("functest_requirements.txt", False, True, True), + ("clitest_requirements.txt", False, True, True), +] + +errors = [] + +for filename, check_upperbound, check_prereleases, check_r in CHECK_MATRIX: + try: + with open(filename, "r") as fd: + for nr, line in enumerate(fd.readlines()): + line = line.strip() + if not line or line.startswith("#"): + continue + try: + req = Requirement.parse(line) + except ValueError: + if line.startswith("git+"): + # The single exception... + if "pulp-smash" not in line: + errors.append(f"{filename}:{nr}: Invalid source requirement: {line}") + elif line.startswith("-r "): + if check_r: + errors.append(f"{filename}:{nr}: Invalid deferred requirement: {line}") + else: + errors.append(f"{filename}:{nr}: Unreadable requirement {line}") + else: + if check_prereleases and req.specifier.prereleases: + # Do not even think about begging for more exceptions! + if ( + not req.name.startswith("opentelemetry") + and req.name != "pulp-docs-client" + ): + errors.append(f"{filename}:{nr}: Prerelease versions found in {line}.") + ops = [op for op, ver in req.specs] + spec = str(req.specs) + if "~=" in ops: + warnings.warn(f"{filename}:{nr}: Please avoid using ~= on {req.name}!") + elif "<" not in ops and "<=" not in ops and "==" not in ops: + if check_upperbound: + errors.append(f"{filename}:{nr}: Upper bound missing in {line}.") + except FileNotFoundError: + # skip this test for plugins that don't use this requirements.txt + pass + +if errors: + print("Dependency issues found:") + print("\n".join(errors)) + exit(1) diff --git a/.ci/scripts/collect_changes.py b/.ci/scripts/collect_changes.py new file mode 100755 index 0000000..3409770 --- /dev/null +++ b/.ci/scripts/collect_changes.py @@ -0,0 +1,103 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import itertools +import os +import re + +import toml +from git import GitCommandError, Repo +from pkg_resources import parse_version + +# Read Towncrier settings +tc_settings = toml.load("pyproject.toml")["tool"]["towncrier"] + +CHANGELOG_FILE = tc_settings.get("filename", "NEWS.rst") +START_STRING = tc_settings.get( + "start_string", + ( + "\n" + if CHANGELOG_FILE.endswith(".md") + else ".. towncrier release notes start\n" + ), +) +TITLE_FORMAT = tc_settings.get("title_format", "{name} {version} ({project_date})") + + +NAME_REGEX = r".*" +VERSION_REGEX = r"([0-9]+\.[0-9]+\.[0-9][0-9ab]*)" +DATE_REGEX = r"[0-9]{4}-[0-9]{2}-[0-9]{2}" +TITLE_REGEX = ( + "(" + + re.escape( + TITLE_FORMAT.format(name="NAME_REGEX", version="VERSION_REGEX", project_date="DATE_REGEX") + ) + .replace("NAME_REGEX", NAME_REGEX) + .replace("VERSION_REGEX", VERSION_REGEX) + .replace("DATE_REGEX", DATE_REGEX) + + ")" +) + + +def get_changelog(repo, branch): + return repo.git.show(f"{branch}:{CHANGELOG_FILE}") + "\n" + + +def _tokenize_changes(splits): + assert len(splits) % 3 == 0 + for i in range(len(splits) // 3): + title = splits[3 * i] + version = parse_version(splits[3 * i + 1]) + yield [version, title + splits[3 * i + 2]] + + +def split_changelog(changelog): + preamble, rest = changelog.split(START_STRING, maxsplit=1) + split_rest = re.split(TITLE_REGEX, rest) + return preamble + START_STRING + split_rest[0], list(_tokenize_changes(split_rest[1:])) + + +def main(): + repo = Repo(os.getcwd()) + remote = repo.remotes[0] + branches = [ref for ref in remote.refs if re.match(r"^([0-9]+)\.([0-9]+)$", ref.remote_head)] + branches.sort(key=lambda ref: parse_version(ref.remote_head), reverse=True) + branches = [ref.name for ref in branches] + + with open(CHANGELOG_FILE, "r") as f: + main_changelog = f.read() + preamble, main_changes = split_changelog(main_changelog) + old_length = len(main_changes) + + for branch in branches: + print(f"Looking at branch {branch}") + try: + changelog = get_changelog(repo, branch) + except GitCommandError: + print("No changelog found on this branch.") + continue + dummy, changes = split_changelog(changelog) + new_changes = sorted(main_changes + changes, key=lambda x: x[0], reverse=True) + # Now remove duplicates (retain the first one) + main_changes = [new_changes[0]] + for left, right in itertools.pairwise(new_changes): + if left[0] != right[0]: + main_changes.append(right) + + new_length = len(main_changes) + if old_length < new_length: + print(f"{new_length - old_length} new versions have been added.") + with open(CHANGELOG_FILE, "w") as fp: + fp.write(preamble) + for change in main_changes: + fp.write(change[1]) + + repo.git.commit("-m", "Update Changelog", "-m" "[noissue]", CHANGELOG_FILE) + + +if __name__ == "__main__": + main() diff --git a/.ci/scripts/validate_commit_message.py b/.ci/scripts/validate_commit_message.py new file mode 100755 index 0000000..6af545a --- /dev/null +++ b/.ci/scripts/validate_commit_message.py @@ -0,0 +1,78 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import re +import sys +from pathlib import Path +import subprocess + + +import os +import warnings +from github import Github + + +NO_ISSUE = "[noissue]" +CHANGELOG_EXTS = [".feature", ".bugfix", ".doc", ".removal", ".misc", ".deprecation"] +sha = sys.argv[1] +message = subprocess.check_output(["git", "log", "--format=%B", "-n 1", sha]).decode("utf-8") + + +KEYWORDS = ["fixes", "closes"] + +g = Github(os.environ.get("GITHUB_TOKEN")) +repo = g.get_repo("pulp/pulp-docs") + + +def __check_status(issue): + gi = repo.get_issue(int(issue)) + if gi.pull_request: + sys.exit(f"Error: issue #{issue} is a pull request.") + if gi.closed_at and "cherry picked from commit" not in message: + warnings.warn( + "When backporting, use the -x flag to append a line that says " + "'(cherry picked from commit ...)' to the original commit message." + ) + sys.exit(f"Error: issue #{issue} is closed.") + + +def __check_changelog(issue): + matches = list(Path("CHANGES").rglob(f"{issue}.*")) + + if len(matches) < 1: + sys.exit(f"Could not find changelog entry in CHANGES/ for {issue}.") + for match in matches: + if match.suffix not in CHANGELOG_EXTS: + sys.exit(f"Invalid extension for changelog entry '{match}'.") + if match.suffix == ".feature" and "cherry picked from commit" in message: + sys.exit(f"Can not backport '{match}' as it is a feature.") + + +print("Checking commit message for {sha}.".format(sha=sha[0:7])) + +# validate the issue attached to the commit +regex = r"(?:{keywords})[\s:]+#(\d+)".format(keywords=("|").join(KEYWORDS)) +pattern = re.compile(regex, re.IGNORECASE) + +issues = pattern.findall(message) + +if issues: + for issue in pattern.findall(message): + __check_status(issue) + __check_changelog(issue) +else: + if NO_ISSUE in message: + print("Commit {sha} has no issues but is tagged {tag}.".format(sha=sha[0:7], tag=NO_ISSUE)) + elif "Merge" in message and "cherry picked from commit" in message: + pass + else: + sys.exit( + "Error: no attached issues found for {sha}. If this was intentional, add " + " '{tag}' to the commit message.".format(sha=sha[0:7], tag=NO_ISSUE) + ) + +print("Commit message for {sha} passed.".format(sha=sha[0:7])) diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..43b5cd6 --- /dev/null +++ b/.flake8 @@ -0,0 +1,33 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template +[flake8] +exclude = ./docs/*,*/migrations/* +per-file-ignores = */__init__.py: F401 + +ignore = E203,W503,Q000,Q003,D100,D104,D106,D200,D205,D400,D401,D402 +max-line-length = 100 + +# Flake8 builtin codes +# -------------------- +# E203: no whitespace around ':'. disabled until https://github.com/PyCQA/pycodestyle/issues/373 is fixed +# W503: This enforces operators before line breaks which is not pep8 or black compatible. + +# Flake8-quotes extension codes +# ----------------------------- +# Q000: double or single quotes only, default is double (don't want to enforce this) +# Q003: Change outer quotes to avoid escaping inner quotes + +# Flake8-docstring extension codes +# -------------------------------- +# D100: missing docstring in public module +# D104: missing docstring in public package +# D106: missing docstring in public nested class (complains about "class Meta:" and documenting those is silly) +# D200: one-line docstring should fit on one line with quotes +# D205: 1 blank line required between summary line and description +# D400: First line should end with a period +# D401: first line should be imperative (nitpicky) +# D402: first line should not be the function’s “signature” (false positives) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..0e7eef5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,23 @@ +--- +name: 🐛 Bug report +about: Create a report to help us improve +title: '' +labels: Issue, Triage-Needed +assignees: '' + +--- + +**Version** +Please provide the versions of the pulpcore and pulp-docs packages in use, and how they are installed. If you are using Pulp via Katello, please provide the Katello version. + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. Please provide links to any previous discussions via Discourse or Bugzilla. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..487f5a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: ✨ Feature request +about: Suggest an idea for this project +title: '' +labels: Feature, Triage-Needed +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md new file mode 100644 index 0000000..f38daa6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.md @@ -0,0 +1,10 @@ +--- +name: 🗒️ Task +about: Documentation, CI/CD, refactors, investigations +title: '' +labels: Task, Triage-Needed +assignees: '' + +--- + + diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..6418af0 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,59 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 90 + +# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 30 + +# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) +onlyLabels: [] + +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - security + - planned + +# Set to true to ignore issues in a project (defaults to false) +exemptProjects: false + +# Set to true to ignore issues in a milestone (defaults to false) +exemptMilestones: false + +# Set to true to ignore issues with an assignee (defaults to false) +exemptAssignees: false + +# Label to use when marking as stale +staleLabel: stale + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 30 +# Limit to only `issues` or `pulls` +only: pulls + +pulls: + markComment: |- + This pull request has been marked 'stale' due to lack of recent activity. If there is no further activity, the PR will be closed in another 30 days. Thank you for your contribution! + + unmarkComment: >- + This pull request is no longer marked for closure. + + closeComment: >- + This pull request has been closed due to inactivity. If you feel this is in error, please reopen the pull request or file a new PR with the relevant details. + +issues: + markComment: |- + This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! + + unmarkComment: >- + This issue is no longer marked for closure. + + closeComment: >- + This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. diff --git a/.github/template_gitref b/.github/template_gitref new file mode 100644 index 0000000..3dcf5a7 --- /dev/null +++ b/.github/template_gitref @@ -0,0 +1 @@ +2021.08.26-321-g24de2b1-dirty diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..d96952c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,44 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: "Build" +on: + workflow_call: + +defaults: + run: + working-directory: "pulp-docs" + +jobs: + build: + runs-on: "ubuntu-latest" + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install packaging twine wheel + echo ::endgroup:: + - name: "Build package" + run: | + python3 setup.py sdist bdist_wheel --python-tag py3 + twine check dist/* + - name: "Upload Package whl" + uses: "actions/upload-artifact@v3" + with: + name: "plugin_package" + path: "pulp-docs/dist/" + if-no-files-found: "error" + retention-days: 5 diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000..bc599a6 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,58 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: "Pulp-Docs changelog update" +on: + push: + branches: + - "main" + paths: + - "CHANGES.rst" + - "CHANGES.md" + workflow_dispatch: + +jobs: + + update-changelog: + runs-on: "ubuntu-latest" + strategy: + fail-fast: false + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install -r doc_requirements.txt + echo ::endgroup:: + + - name: "Fake api schema" + run: | + mkdir -p docs/_build/html + echo "{}" > docs/_build/html/api.json + mkdir -p docs/_static + echo "{}" > docs/_static/api.json + - name: "Build Docs" + run: | + make diagrams html + working-directory: "./docs" + env: + PULP_CONTENT_ORIGIN: "http://localhost/" + + - name: "Publish changlog to pulpproject.org" + run: | + .github/workflows/scripts/publish_docs.sh changelog ${GITHUB_REF##*/} + env: + PULP_DOCS_KEY: "${{ secrets.PULP_DOCS_KEY }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35b83fb..e00877d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,25 +1,93 @@ -# workflow from: https://squidfunk.github.io/mkdocs-material/publishing-your-site/ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template -name: ci -on: - push: - branches: - - master - - main - workflow_dispatch: +--- +name: "Pulp-Docs CI" +on: {pull_request: {branches: ['*']}} + +concurrency: + group: ${{ github.ref_name }}-${{ github.workflow }} + cancel-in-progress: true + +defaults: + run: + working-directory: "pulp-docs" jobs: + check-commits: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + path: "pulp-docs" + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install requests pygithub + echo ::endgroup:: + - name: "Check commit message" + if: github.event_name == 'pull_request' + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + run: | + .github/workflows/scripts/check_commit.sh + - name: "Verify requirements files" + run: | + python .ci/scripts/check_requirements.py + + lint: + uses: "./.github/workflows/lint.yml" + build: - runs-on: ubuntu-latest + needs: "lint" + uses: "./.github/workflows/build.yml" + + test: + needs: "build" + uses: "./.github/workflows/test.yml" + + deprecations: + runs-on: "ubuntu-latest" + if: github.base_ref == 'main' + needs: "test" steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - name: "Create working directory" + run: | + mkdir -p "pulp-docs" + working-directory: "." + - name: "Download Deprecations" + uses: actions/download-artifact@v3 with: - python-version: 3.8 - - name: + name: "deprecations" + path: "pulp-docs" + - name: "Print deprecations" + run: | + cat deprecations-*.txt | sort -u + ! cat deprecations-*.txt | grep '[^[:space:]]' + + ready-to-ship: + # This is a dummy dependent task to have a single entry for the branch protection rules. + runs-on: "ubuntu-latest" + needs: + - "check-commits" + - "lint" + - "test" + if: "always()" + steps: + - name: "Collect needed jobs results" + working-directory: "." run: | - pip install build - python -m build - pip install dist/*.whl - pulp-docs build - tree site + echo '${{toJson(needs)}}' | jq -r 'to_entries[]|select(.value.result!="success")|.key + ": " + .value.result' + echo '${{toJson(needs)}}' | jq -e 'to_entries|map(select(.value.result!="success"))|length == 0' + echo "CI says: Looks good!" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..a0fded2 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,42 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template +name: "Pulp-Docs CodeQL" + +on: + workflow_dispatch: + schedule: + - cron: '37 1 * * 6' + +concurrency: + group: ${{ github.ref_name }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'python' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/create-branch.yml b/.github/workflows/create-branch.yml new file mode 100644 index 0000000..354e447 --- /dev/null +++ b/.github/workflows/create-branch.yml @@ -0,0 +1,106 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: Create New Release Branch +on: + workflow_dispatch: + +env: + RELEASE_WORKFLOW: true + +jobs: + create-branch: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + path: "pulp-docs" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install bump2version jinja2 pyyaml packaging + echo ::endgroup:: + + - name: "Setting secrets" + working-directory: "pulp-docs" + run: | + python3 .github/workflows/scripts/secrets.py "$SECRETS_CONTEXT" + env: + SECRETS_CONTEXT: "${{ toJson(secrets) }}" + + - name: Determine new branch name + working-directory: pulp-docs + run: | + # Just to be sure... + git checkout main + NEW_BRANCH="$(bump2version --dry-run --list release | sed -Ene 's/^new_version=([[:digit:]]+\.[[:digit:]]+)\..*$/\1/p')" + if [ -z "$NEW_BRANCH" ] + then + echo Could not determine the new branch name. + exit 1 + fi + echo "NEW_BRANCH=${NEW_BRANCH}" >> "$GITHUB_ENV" + + - name: Create release branch + working-directory: pulp-docs + run: | + git branch "${NEW_BRANCH}" + + - name: Bump version on main branch + working-directory: pulp-docs + run: | + bump2version --no-commit minor + + - name: Remove entries from CHANGES directory + working-directory: pulp-docs + run: | + find CHANGES -type f -regex ".*\.\(bugfix\|doc\|feature\|misc\|deprecation\|removal\)" -exec git rm {} + + + - name: Checkout plugin template + uses: actions/checkout@v4 + with: + repository: pulp/plugin_template + path: plugin_template + fetch-depth: 0 + + - name: Update CI branches in template_config + working-directory: plugin_template + run: | + python3 ./plugin-template pulp-docs --github --latest-release-branch "${NEW_BRANCH}" + git add -A + + - name: Make a PR with version bump and without CHANGES/* + uses: peter-evans/create-pull-request@v6 + with: + path: pulp-docs + token: ${{ secrets.RELEASE_TOKEN }} + committer: pulpbot + author: pulpbot + branch: minor-version-bump + base: main + title: Bump minor version + body: '[noissue]' + commit-message: | + Bump minor version + [noissue] + delete-branch: true + + - name: Push release branch + working-directory: pulp-docs + run: | + git push origin "${NEW_BRANCH}" diff --git a/.github/workflows/kanban.yml b/.github/workflows/kanban.yml new file mode 100644 index 0000000..71d603a --- /dev/null +++ b/.github/workflows/kanban.yml @@ -0,0 +1,103 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template +# Manage issues in a project board using https://github.com/leonsteinhaeuser/project-beta-automations + +--- +name: Kanban +on: + pull_request_target: + issues: + types: + - labeled + - reopened + - assigned + - closed + +env: + free_to_take: Free to take + in_progress: In Progress + needs_review: Needs review + done: Done + +jobs: + # only prio-list labeled items should be added to the board + add-to-project-board: + if: github.event_name == 'issues' && contains(github.event.issue.labels.*.name, 'prio-list') && contains(fromJson('["labeled", "reopened"]'), github.event.action) + runs-on: ubuntu-latest + steps: + - name: Add issue to Free-to-take list + uses: leonsteinhaeuser/project-beta-automations@v2.0.0 + with: + gh_token: ${{ secrets.RELEASE_TOKEN }} + organization: pulp + project_id: 8 + resource_node_id: ${{ github.event.issue.node_id }} + operation_mode: status + status_value: ${{ env.free_to_take }} # Target status + + move-to-inprogress: + if: github.event_name == 'issues' && github.event.action == 'assigned' + runs-on: ubuntu-latest + steps: + - name: Move an issue to the In Progress column + uses: leonsteinhaeuser/project-beta-automations@v2.0.0 + with: + gh_token: ${{ secrets.RELEASE_TOKEN }} + organization: pulp + project_id: 8 + resource_node_id: ${{ github.event.issue.node_id }} + operation_mode: status + status_value: ${{ env.in_progress }} # Target status + + find-linked-issues: + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-latest + name: Find issues linked to a PR + outputs: + linked-issues: ${{ steps.linked-issues.outputs.issues }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Get Linked Issues Action + uses: kin/gh-action-get-linked-issues@v1.0 + id: linked-issues + with: + access-token: ${{ secrets.RELEASE_TOKEN }} + + move-to-needs-review: + if: github.event_name == 'pull_request_target' && contains(fromJson(needs.find-linked-issues.outputs.linked-issues).*.issue.state, 'open') + runs-on: ubuntu-latest + name: Move linked issues to Needs Review + needs: find-linked-issues + strategy: + max-parallel: 3 + matrix: + issues: ${{ fromJSON(needs.find-linked-issues.outputs.linked-issues) }} + steps: + - name: Move to Needs Review + uses: leonsteinhaeuser/project-beta-automations@v2.0.0 + with: + gh_token: ${{ secrets.RELEASE_TOKEN }} + organization: pulp + project_id: 8 + resource_node_id: ${{ matrix.issues.issue.node_id }} + operation_mode: status + status_value: ${{ env.needs_review }} # Target status + + move-to-done: + if: github.event_name == 'issues' && github.event.action == 'closed' + runs-on: ubuntu-latest + steps: + - name: Move an issue to the Done column + uses: leonsteinhaeuser/project-beta-automations@v2.0.0 + with: + gh_token: ${{ secrets.RELEASE_TOKEN }} + organization: pulp + project_id: 8 + resource_node_id: ${{ github.event.issue.node_id }} + operation_mode: status + status_value: ${{ env.done }} # Target status diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..8c49901 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,62 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: "Lint" +on: + workflow_call: + +defaults: + run: + working-directory: "pulp-docs" + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install -r lint_requirements.txt + echo ::endgroup:: + + - name: Lint workflow files + run: | + yamllint -s -d '{extends: relaxed, rules: {line-length: disable}}' .github/workflows + + # run black separately from flake8 to get a diff + - name: Run black + run: | + black --version + black --check --diff . + + # Lint code. + - name: Run flake8 + run: flake8 + + - name: Run extra lint checks + run: "[ ! -x .ci/scripts/extra_linting.sh ] || .ci/scripts/extra_linting.sh" + + # check for any files unintentionally left out of MANIFEST.in + - name: Check manifest + run: check-manifest + + - name: Check for pulpcore imports outside of pulpcore.plugin + run: sh .ci/scripts/check_pulpcore_imports.sh + + - name: Check for gettext problems + run: sh .ci/scripts/check_gettext.sh diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000..253e57f --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,96 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: "Pulp-Docs Nightly CI" +on: + schedule: + # * is a special character in YAML so you have to quote this string + # runs at 3:00 UTC daily + - cron: '00 3 * * *' + workflow_dispatch: + +defaults: + run: + working-directory: "pulp-docs" + +concurrency: + group: "${{ github.ref_name }}-${{ github.workflow }}" + cancel-in-progress: true + +jobs: + build: + uses: "./.github/workflows/build.yml" + + test: + needs: "build" + uses: "./.github/workflows/test.yml" + + changelog: + runs-on: ubuntu-latest + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + path: "pulp-docs" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install gitpython toml + echo ::endgroup:: + + - name: "Configure Git with pulpbot name and email" + run: | + git config --global user.name 'pulpbot' + git config --global user.email 'pulp-infra@redhat.com' + + - name: Collect changes from all branches + run: python .ci/scripts/collect_changes.py + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.RELEASE_TOKEN }} + title: "Update Changelog" + body: "" + branch: "changelog/update" + delete-branch: true + path: "pulp-docs" + + publish: + runs-on: ubuntu-latest + needs: test + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - uses: actions/download-artifact@v3 + with: + name: "plugin_package" + path: "pulp-docs/dist/" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install requests 'packaging~=21.3' mkdocs pymdown-extensions 'Jinja2<3.1' + echo ::endgroup:: + + - name: "Set environment variables" + run: | + echo "TEST=${{ matrix.env.TEST }}" >> $GITHUB_ENV diff --git a/.github/workflows/pr_checks.yml b/.github/workflows/pr_checks.yml new file mode 100644 index 0000000..c9aafa4 --- /dev/null +++ b/.github/workflows/pr_checks.yml @@ -0,0 +1,62 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: Pulp-Docs PR static checks +on: + pull_request_target: + types: [opened, synchronize, reopened] + +# This workflow runs with elevated permissions. +# Do not even think about running a single bit of code from the PR. +# Static analysis should be fine however. + +concurrency: + group: ${{ github.event.pull_request.number }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + single_commit: + runs-on: ubuntu-latest + name: Label multiple commit PR + permissions: + pull-requests: write + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + - name: Commit Count Check + run: | + git fetch origin ${{ github.event.pull_request.head.sha }} + echo "COMMIT_COUNT=$(git log --oneline --no-merges origin/${{ github.base_ref }}..${{ github.event.pull_request.head.sha }} | wc -l)" >> "$GITHUB_ENV" + - uses: actions/github-script@v7 + with: + script: | + const labelName = "multi-commit"; + const { COMMIT_COUNT } = process.env; + + if (COMMIT_COUNT == 1) + { + try { + await github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: labelName, + }); + } catch(err) { + } + } + else + { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [labelName], + }); + } diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..e05e702 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,263 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: "Pulp-Docs Publish Release" +on: + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+" + +defaults: + run: + working-directory: "pulp-docs" + +jobs: + build: + uses: "./.github/workflows/build.yml" + + build-bindings-docs: + needs: + - "build" + runs-on: "ubuntu-latest" + # Install scripts expect TEST to be set, 'docs' is most appropriate even though we don't run tests + env: + TEST: "docs" + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + repository: "pulp/pulp-openapi-generator" + path: "pulp-openapi-generator" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - uses: "actions/download-artifact@v3" + with: + name: "plugin_package" + path: "pulp-docs/dist/" + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "2.6" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install towncrier twine wheel httpie docker netaddr boto3 ansible mkdocs + echo "HTTPIE_CONFIG_DIR=$GITHUB_WORKSPACE/pulp-docs/.ci/assets/httpie/" >> $GITHUB_ENV + echo ::endgroup:: + + # Building the bindings and docs requires accessing the OpenAPI specs endpoint, so we need to + # setup the Pulp instance. + - name: "Before Install" + run: | + .github/workflows/scripts/before_install.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + + - name: "Install" + run: | + .github/workflows/scripts/install.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + + - name: "Install Python client" + run: | + .github/workflows/scripts/install_python_client.sh + shell: "bash" + - name: "Install Ruby client" + run: | + .github/workflows/scripts/install_ruby_client.sh + shell: "bash" + - name: "Upload python client packages" + uses: "actions/upload-artifact@v3" + with: + name: "python-client.tar" + path: "pulp-docs/pulp-docs-python-client.tar" + if-no-files-found: "error" + + - name: "Upload python client docs" + uses: "actions/upload-artifact@v3" + with: + name: "python-client-docs.tar" + path: "pulp-docs/pulp-docs-python-client-docs.tar" + if-no-files-found: "error" + - name: "Upload ruby client packages" + uses: "actions/upload-artifact@v3" + with: + name: "ruby-client.tar" + path: "pulp-docs/pulp-docs-ruby-client.tar" + if-no-files-found: "error" + + - name: "Logs" + if: always() + run: | + echo "Need to debug? Please check: https://github.com/marketplace/actions/debugging-with-tmate" + http --timeout 30 --check-status --pretty format --print hb "https://pulp${PULP_API_ROOT}api/v3/status/" || true + docker images || true + docker ps -a || true + docker logs pulp || true + docker exec pulp ls -latr /etc/yum.repos.d/ || true + docker exec pulp cat /etc/yum.repos.d/* || true + docker exec pulp bash -c "pip3 list && pip3 install pipdeptree && pipdeptree" + publish-package: + runs-on: "ubuntu-latest" + needs: + - "build-bindings-docs" + + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - uses: "actions/download-artifact@v3" + with: + name: "plugin_package" + path: "pulp-docs/dist/" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install twine + echo ::endgroup:: + + - name: "Setting secrets" + run: | + python3 .github/workflows/scripts/secrets.py "$SECRETS_CONTEXT" + env: + SECRETS_CONTEXT: "${{ toJson(secrets) }}" + + - name: "Deploy plugin to pypi" + run: | + .github/workflows/scripts/publish_plugin_pypi.sh ${{ github.ref_name }} + publish-python-bindings: + runs-on: "ubuntu-latest" + needs: + - "build-bindings-docs" + + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - name: "Download Python client" + uses: "actions/download-artifact@v3" + with: + name: "python-client.tar" + path: "pulp-docs/" + + - name: "Untar python client packages" + run: | + tar -xvf pulp-docs-python-client.tar + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install twine + echo ::endgroup:: + + - name: "Setting secrets" + run: | + python3 .github/workflows/scripts/secrets.py "$SECRETS_CONTEXT" + env: + SECRETS_CONTEXT: "${{ toJson(secrets) }}" + + - name: "Publish client to pypi" + run: | + bash .github/workflows/scripts/publish_client_pypi.sh ${{ github.ref_name }} + publish-ruby-bindings: + runs-on: "ubuntu-latest" + needs: + - "build-bindings-docs" + + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - name: "Download Ruby client" + uses: "actions/download-artifact@v3" + with: + name: "ruby-client.tar" + path: "pulp-docs/" + + - name: "Untar Ruby client packages" + run: | + tar -xvf pulp-docs-ruby-client.tar + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "2.6" + + - name: "Setting secrets" + run: | + python3 .github/workflows/scripts/secrets.py "$SECRETS_CONTEXT" + env: + SECRETS_CONTEXT: "${{ toJson(secrets) }}" + + - name: "Publish client to rubygems" + run: | + bash .github/workflows/scripts/publish_client_gem.sh ${{ github.ref_name }} + + create-gh-release: + runs-on: "ubuntu-latest" + needs: + - "build-bindings-docs" + - "publish-package" + - "publish-python-bindings" + - "publish-ruby-bindings" + + steps: + - name: "Create release on GitHub" + uses: "actions/github-script@v7" + env: + TAG_NAME: "${{ github.ref_name }}" + with: + script: | + const { TAG_NAME } = process.env; + + await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: TAG_NAME, + make_latest: "legacy", + }); diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ef0e1f1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,60 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: Pulp-Docs Release Pipeline +on: + workflow_dispatch: + +defaults: + run: + working-directory: "pulp-docs" + +jobs: + build-artifacts: + runs-on: "ubuntu-latest" + + strategy: + fail-fast: false + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + path: "pulp-docs" + token: ${{ secrets.RELEASE_TOKEN }} + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install bump2version towncrier + echo ::endgroup:: + + - name: "Configure Git with pulpbot name and email" + run: | + git config --global user.name 'pulpbot' + git config --global user.email 'pulp-infra@redhat.com' + + - name: "Setting secrets" + run: | + python3 .github/workflows/scripts/secrets.py "$SECRETS_CONTEXT" + env: + SECRETS_CONTEXT: "${{ toJson(secrets) }}" + + - name: "Tag the release" + run: | + .github/workflows/scripts/release.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" diff --git a/.github/workflows/scripts/before_install.sh b/.github/workflows/scripts/before_install.sh new file mode 100755 index 0000000..dd31fcb --- /dev/null +++ b/.github/workflows/scripts/before_install.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +set -mveuo pipefail + +if [ "${GITHUB_REF##refs/heads/}" = "${GITHUB_REF}" ] +then + BRANCH_BUILD=0 +else + BRANCH_BUILD=1 + BRANCH="${GITHUB_REF##refs/heads/}" +fi +if [ "${GITHUB_REF##refs/tags/}" = "${GITHUB_REF}" ] +then + TAG_BUILD=0 +else + TAG_BUILD=1 + BRANCH="${GITHUB_REF##refs/tags/}" +fi + +COMMIT_MSG=$(git log --format=%B --no-merges -1) +export COMMIT_MSG + +COMPONENT_VERSION=$(sed -ne "s/\s*version.*=.*['\"]\(.*\)['\"][\s,]*/\1/p" setup.py) + +mkdir .ci/ansible/vars || true +echo "---" > .ci/ansible/vars/main.yaml +echo "legacy_component_name: pulp_docs" >> .ci/ansible/vars/main.yaml +echo "component_name: pulp-docs" >> .ci/ansible/vars/main.yaml +echo "component_version: '${COMPONENT_VERSION}'" >> .ci/ansible/vars/main.yaml + +export PRE_BEFORE_INSTALL=$PWD/.github/workflows/scripts/pre_before_install.sh +export POST_BEFORE_INSTALL=$PWD/.github/workflows/scripts/post_before_install.sh + +if [ -f $PRE_BEFORE_INSTALL ]; then + source $PRE_BEFORE_INSTALL +fi + +if [[ -n $(echo -e $COMMIT_MSG | grep -P "Required PR:.*") ]]; then + echo "The Required PR mechanism has been removed. Consider adding a scm requirement to requirements.txt." + exit 1 +fi + +if [ "$GITHUB_EVENT_NAME" = "pull_request" ] || [ "${BRANCH_BUILD}" = "1" -a "${BRANCH}" != "main" ] +then + echo $COMMIT_MSG | sed -n -e 's/.*CI Base Image:\s*\([-_/[:alnum:]]*:[-_[:alnum:]]*\).*/ci_base: "\1"/p' >> .ci/ansible/vars/main.yaml +fi + +for i in {1..3} +do + ansible-galaxy collection install "amazon.aws:1.5.0" && s=0 && break || s=$? && sleep 3 +done +if [[ $s -gt 0 ]] +then + echo "Failed to install amazon.aws" + exit $s +fi + +if [[ "$TEST" = "lowerbounds" ]]; then + python3 .ci/scripts/calc_deps_lowerbounds.py > lowerbounds_constraints.txt + sed -i 's/\[.*\]//g' lowerbounds_constraints.txt +fi + +if [ -f $POST_BEFORE_INSTALL ]; then + source $POST_BEFORE_INSTALL +fi diff --git a/.github/workflows/scripts/before_script.sh b/.github/workflows/scripts/before_script.sh new file mode 100755 index 0000000..ff40446 --- /dev/null +++ b/.github/workflows/scripts/before_script.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +set -euv + +source .github/workflows/scripts/utils.sh + +export PRE_BEFORE_SCRIPT=$PWD/.github/workflows/scripts/pre_before_script.sh +export POST_BEFORE_SCRIPT=$PWD/.github/workflows/scripts/post_before_script.sh + +if [[ -f $PRE_BEFORE_SCRIPT ]]; then + source $PRE_BEFORE_SCRIPT +fi + +# Developers should be able to reproduce the containers with this config +echo "CI vars:" +tail -v -n +1 .ci/ansible/vars/main.yaml + +# Developers often want to know the final pulp config +echo "PULP CONFIG:" +tail -v -n +1 .ci/ansible/settings/settings.* ~/.config/pulp_smash/settings.json + +echo "Containerfile:" +tail -v -n +1 .ci/ansible/Containerfile + +# Needed for some functional tests +cmd_prefix bash -c "echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/nopasswd" +cmd_prefix bash -c "usermod -a -G wheel pulp" + +SCENARIOS=("pulp" "performance" "azure" "gcp" "s3" "generate-bindings" "lowerbounds") +if [[ " ${SCENARIOS[*]} " =~ " ${TEST} " ]]; then + # Many functional tests require these + cmd_prefix dnf install -yq lsof which +fi + +if [[ "${REDIS_DISABLED:-false}" == true ]]; then + cmd_prefix bash -c "s6-rc -d change redis" + echo "The Redis service was disabled for $TEST" +fi + +if [[ -f $POST_BEFORE_SCRIPT ]]; then + source $POST_BEFORE_SCRIPT +fi + +# Lots of plugins try to use this path, and throw warnings if they cannot access it. +cmd_prefix mkdir /.pytest_cache +cmd_prefix chown pulp:pulp /.pytest_cache diff --git a/.github/workflows/scripts/check_commit.sh b/.github/workflows/scripts/check_commit.sh new file mode 100755 index 0000000..b0dba3c --- /dev/null +++ b/.github/workflows/scripts/check_commit.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")/../../.." + +set -euv + +for SHA in $(curl -H "Authorization: token $GITHUB_TOKEN" "$GITHUB_CONTEXT" | jq -r '.[].sha') +do + python3 .ci/scripts/validate_commit_message.py "$SHA" + VALUE=$? + if [ "$VALUE" -gt 0 ]; then + exit $VALUE + fi +done diff --git a/.github/workflows/scripts/docs-publisher.py b/.github/workflows/scripts/docs-publisher.py new file mode 100755 index 0000000..00e784e --- /dev/null +++ b/.github/workflows/scripts/docs-publisher.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import argparse +import subprocess +import os +import re +from shutil import rmtree +import tempfile +import requests +import json +from packaging import version + +WORKING_DIR = os.environ["WORKSPACE"] + +VERSION_REGEX = r"(\s*)(version)(\s*)(=)(\s*)(['\"])(.*)(['\"])(.*)" +RELEASE_REGEX = r"(\s*)(release)(\s*)(=)(\s*)(['\"])(.*)(['\"])(.*)" + +USERNAME = "doc_builder_pulp_docs" +HOSTNAME = "8.43.85.236" + +SITE_ROOT = "/var/www/docs.pulpproject.org/pulp_docs/" + + +def make_directory_with_rsync(remote_paths_list): + """ + Ensure the remote directory path exists. + + :param remote_paths_list: The list of parameters. e.g. ['en', 'latest'] to be en/latest on the + remote. + :type remote_paths_list: a list of strings, with each string representing a directory. + """ + try: + tempdir_path = tempfile.mkdtemp() + cwd = os.getcwd() + os.chdir(tempdir_path) + os.makedirs(os.sep.join(remote_paths_list)) + remote_path_arg = "%s@%s:%s%s" % ( + USERNAME, + HOSTNAME, + SITE_ROOT, + remote_paths_list[0], + ) + local_path_arg = tempdir_path + os.sep + remote_paths_list[0] + os.sep + rsync_command = ["rsync", "-avzh", local_path_arg, remote_path_arg] + exit_code = subprocess.call(rsync_command) + if exit_code != 0: + raise RuntimeError("An error occurred while creating remote directories.") + finally: + rmtree(tempdir_path) + os.chdir(cwd) + + +def ensure_dir(target_dir, clean=True): + """ + Ensure that the directory specified exists and is empty. + + By default this will delete the directory if it already exists + + :param target_dir: The directory to process + :type target_dir: str + :param clean: Whether or not the directory should be removed and recreated + :type clean: bool + """ + if clean: + rmtree(target_dir, ignore_errors=True) + try: + os.makedirs(target_dir) + except OSError: + pass + + +def main(): + """ + Builds documentation using the 'make html' command and rsyncs to docs.pulpproject.org. + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "--build-type", required=True, help="Build type: nightly, tag or changelog." + ) + parser.add_argument("--branch", required=True, help="Branch or tag name.") + opts = parser.parse_args() + + build_type = opts.build_type + + branch = opts.branch + + publish_at_root = False + + # rsync the docs + print("rsync the docs") + docs_directory = os.sep.join([WORKING_DIR, "docs"]) + local_path_arg = os.sep.join([docs_directory, "_build", "html"]) + os.sep + if build_type == "nightly": + # This is a nightly build + remote_path_arg = "%s@%s:%sen/%s/%s/" % ( + USERNAME, + HOSTNAME, + SITE_ROOT, + branch, + build_type, + ) + make_directory_with_rsync(["en", branch, build_type]) + rsync_command = ["rsync", "-avzh", "--delete", local_path_arg, remote_path_arg] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + elif build_type == "tag": + if (not re.search("[a-zA-Z]", branch) or "post" in branch) and len(branch.split(".")) > 2: + # Only publish docs at the root if this is the latest version + r = requests.get("https://pypi.org/pypi/pulp-docs/json") + latest_version = version.parse(json.loads(r.text)["info"]["version"]) + docs_version = version.parse(branch) + # This is to mitigate delays on PyPI which doesn't update metadata in timely manner. + # It doesn't prevent incorrect docs being published at root if 2 releases are done close + # to each other, within PyPI delay. E.g. Release 3.11.0 an then 3.10.1 immediately + # after. + if docs_version >= latest_version: + publish_at_root = True + # Post releases should use the x.y.z part of the version string to form a path + if "post" in branch: + branch = ".".join(branch.split(".")[:-1]) + + # This is a GA build. + # publish to the root of docs.pulpproject.org + if publish_at_root: + version_components = branch.split(".") + x_y_version = "{}.{}".format(version_components[0], version_components[1]) + remote_path_arg = "%s@%s:%s" % (USERNAME, HOSTNAME, SITE_ROOT) + rsync_command = [ + "rsync", + "-avzh", + "--delete", + "--exclude", + "en", + "--omit-dir-times", + local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + # publish to docs.pulpproject.org/en/3.y/ + make_directory_with_rsync(["en", x_y_version]) + remote_path_arg = "%s@%s:%sen/%s/" % ( + USERNAME, + HOSTNAME, + SITE_ROOT, + x_y_version, + ) + rsync_command = [ + "rsync", + "-avzh", + "--delete", + "--omit-dir-times", + local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + # publish to docs.pulpproject.org/en/3.y.z/ + make_directory_with_rsync(["en", branch]) + remote_path_arg = "%s@%s:%sen/%s/" % (USERNAME, HOSTNAME, SITE_ROOT, branch) + rsync_command = [ + "rsync", + "-avzh", + "--delete", + "--omit-dir-times", + local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + else: + # This is a pre-release + make_directory_with_rsync(["en", branch]) + remote_path_arg = "%s@%s:%sen/%s/%s/" % ( + USERNAME, + HOSTNAME, + SITE_ROOT, + branch, + build_type, + ) + rsync_command = [ + "rsync", + "-avzh", + "--delete", + "--exclude", + "nightly", + "--exclude", + "testing", + local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + # publish to docs.pulpproject.org/en/3.y/ + version_components = branch.split(".") + x_y_version = "{}.{}".format(version_components[0], version_components[1]) + make_directory_with_rsync(["en", x_y_version]) + remote_path_arg = "%s@%s:%sen/%s/" % ( + USERNAME, + HOSTNAME, + SITE_ROOT, + x_y_version, + ) + rsync_command = [ + "rsync", + "-avzh", + "--delete", + "--omit-dir-times", + local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + # publish to docs.pulpproject.org/en/3.y.z/ + make_directory_with_rsync(["en", branch]) + remote_path_arg = "%s@%s:%sen/%s/" % (USERNAME, HOSTNAME, SITE_ROOT, branch) + rsync_command = [ + "rsync", + "-avzh", + "--delete", + "--omit-dir-times", + local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + elif build_type == "changelog": + if branch != "main": + raise RuntimeError("Can only publish CHANGELOG from main") + # Publish the CHANGELOG from main branch at the root directory + remote_path_arg = "%s@%s:%s" % (USERNAME, HOSTNAME, SITE_ROOT) + changelog_local_path_arg = os.path.join(local_path_arg, "changes.html") + rsync_command = [ + "rsync", + "-vzh", + "--omit-dir-times", + changelog_local_path_arg, + remote_path_arg, + ] + exit_code = subprocess.call(rsync_command, cwd=docs_directory) + if exit_code != 0: + raise RuntimeError("An error occurred while pushing docs.") + else: + raise RuntimeError("Build type must be either 'nightly', 'tag' or 'changelog'.") + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/scripts/install.sh b/.github/workflows/scripts/install.sh new file mode 100755 index 0000000..a57a16c --- /dev/null +++ b/.github/workflows/scripts/install.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. +REPO_ROOT="$PWD" + +set -euv + +source .github/workflows/scripts/utils.sh + +PLUGIN_VERSION="$(sed -n -e 's/^\s*current_version\s*=\s*//p' .bumpversion.cfg | python -c 'from packaging.version import Version; print(Version(input()))')" +PLUGIN_SOURCE="./pulp-docs/dist/pulp_docs-${PLUGIN_VERSION}-py3-none-any.whl" + +export PULP_API_ROOT="/pulp/" + +PIP_REQUIREMENTS=("pulp-cli") +if [[ "$TEST" = "docs" || "$TEST" = "publish" ]] +then + PIP_REQUIREMENTS+=("-r" "doc_requirements.txt") +fi + +pip install ${PIP_REQUIREMENTS[*]} + + + +cd .ci/ansible/ + +cat >> vars/main.yaml << VARSYAML +image: + name: pulp + tag: "ci_build" +plugins: + - name: pulp-docs + source: "${PLUGIN_SOURCE}" +VARSYAML +if [[ -f ../../ci_requirements.txt ]]; then + cat >> vars/main.yaml << VARSYAML + ci_requirements: true +VARSYAML +fi +if [ "$TEST" = "lowerbounds" ]; then + cat >> vars/main.yaml << VARSYAML + lowerbounds: true +VARSYAML +fi + +cat >> vars/main.yaml << VARSYAML +services: + - name: pulp + image: "pulp:ci_build" + volumes: + - ./settings:/etc/pulp + - ./ssh:/keys/ + - ~/.config:/var/lib/pulp/.config + - ../../../pulp-openapi-generator:/root/pulp-openapi-generator + env: + PULP_WORKERS: "4" + PULP_HTTPS: "true" +VARSYAML + +cat >> vars/main.yaml << VARSYAML +pulp_env: {} +pulp_settings: null +pulp_scheme: https +pulp_default_container: ghcr.io/pulp/pulp-ci-centos9:latest +VARSYAML + +echo "PULP_API_ROOT=${PULP_API_ROOT}" >> "$GITHUB_ENV" + +if [ "${PULP_API_ROOT:-}" ]; then + sed -i -e '$a api_root: "'"$PULP_API_ROOT"'"' vars/main.yaml +fi + +pulp config create --base-url https://pulp --api-root "$PULP_API_ROOT" --username "admin" --password "password" + + +ansible-playbook build_container.yaml +ansible-playbook start_container.yaml + +# .config needs to be accessible by the pulp user in the container, but some +# files will likely be modified on the host by post/pre scripts. +chmod 777 ~/.config/pulp_smash/ +chmod 666 ~/.config/pulp_smash/settings.json + +sudo chown -R 700:700 ~/.config +echo ::group::SSL +# Copy pulp CA +sudo docker cp pulp:/etc/pulp/certs/pulp_webserver.crt /usr/local/share/ca-certificates/pulp_webserver.crt + +# Hack: adding pulp CA to certifi.where() +CERTIFI=$(python -c 'import certifi; print(certifi.where())') +cat /usr/local/share/ca-certificates/pulp_webserver.crt | sudo tee -a "$CERTIFI" > /dev/null +if [[ "$TEST" = "azure" ]]; then + cat /usr/local/share/ca-certificates/azcert.crt | sudo tee -a "$CERTIFI" > /dev/null +fi + +# Hack: adding pulp CA to default CA file +CERT=$(python -c 'import ssl; print(ssl.get_default_verify_paths().openssl_cafile)') +cat "$CERTIFI" | sudo tee -a "$CERT" > /dev/null + +# Updating certs +sudo update-ca-certificates +echo ::endgroup:: + +# Add our azcert.crt certificate to the container image along with the certificates from certifi +# so that we can use HTTPS with our fake Azure CI. certifi is self-contained and doesn't allow +# extension or modification of the trust store, so we do a weird and hacky thing (above) where we just +# overwrite or append to certifi's trust store behind it's back. +# +# We do this for both the CI host and the CI image. +if [[ "$TEST" = "azure" ]]; then + AZCERTIFI=$(/opt/az/bin/python3 -c 'import certifi; print(certifi.where())') + PULPCERTIFI=$(cmd_prefix python3 -c 'import certifi; print(certifi.where())') + cat /usr/local/share/ca-certificates/azcert.crt >> $AZCERTIFI + cat /usr/local/share/ca-certificates/azcert.crt | cmd_stdin_prefix tee -a "$PULPCERTIFI" > /dev/null + cat /usr/local/share/ca-certificates/azcert.crt | cmd_stdin_prefix tee -a /etc/pki/tls/cert.pem > /dev/null + AZURE_STORAGE_CONNECTION_STRING='DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://ci-azurite:10000/devstoreaccount1;' + az storage container create --name pulp-test --connection-string $AZURE_STORAGE_CONNECTION_STRING +fi + +echo ::group::PIP_LIST +cmd_prefix bash -c "pip3 list && pip3 install pipdeptree && pipdeptree" +echo ::endgroup:: diff --git a/.github/workflows/scripts/install_python_client.sh b/.github/workflows/scripts/install_python_client.sh new file mode 100755 index 0000000..8134f14 --- /dev/null +++ b/.github/workflows/scripts/install_python_client.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -mveuo pipefail + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +source .github/workflows/scripts/utils.sh + +PULP_URL="${PULP_URL:-https://pulp}" +export PULP_URL +PULP_API_ROOT="${PULP_API_ROOT:-/pulp/}" +export PULP_API_ROOT + +REPORTED_STATUS="$(pulp status)" +REPORTED_VERSION="$(echo "$REPORTED_STATUS" | jq --arg plugin "pulp-docs" -r '.versions[] | select(.component == $plugin) | .version')" +VERSION="$(echo "$REPORTED_VERSION" | python -c 'from packaging.version import Version; print(Version(input()))')" + +pushd ../pulp-openapi-generator +rm -rf pulp_docs-client + +if pulp debug has-plugin --name "core" --specifier ">=3.44.0.dev" +then + curl --fail-with-body -k -o api.json "${PULP_URL}${PULP_API_ROOT}api/v3/docs/api.json?bindings&component=pulp-docs" + USE_LOCAL_API_JSON=1 ./generate.sh pulp_docs python "$VERSION" +else + ./generate.sh pulp_docs python "$VERSION" +fi + +pushd pulp_docs-client +python setup.py sdist bdist_wheel --python-tag py3 + +twine check "dist/pulp_docs_client-$VERSION-py3-none-any.whl" +twine check "dist/pulp_docs-client-$VERSION.tar.gz" + +cmd_prefix pip3 install "/root/pulp-openapi-generator/pulp_docs-client/dist/pulp_docs_client-${VERSION}-py3-none-any.whl" +tar cvf ../../pulp-docs/pulp-docs-python-client.tar ./dist + +find ./docs/* -exec sed -i 's/Back to README/Back to HOME/g' {} \; +find ./docs/* -exec sed -i 's/README//g' {} \; +cp README.md docs/index.md +sed -i 's/docs\///g' docs/index.md +find ./docs/* -exec sed -i 's/\.md//g' {} \; + +cat >> mkdocs.yml << DOCSYAML +--- +site_name: Pulp-Docs Client +site_description: Pulp-Docs bindings +site_author: Pulp Team +site_url: https://docs.pulpproject.org/pulp_docs_client/ +repo_name: pulp/pulp_docs +repo_url: https://github.com/pulp/pulp_docs +theme: readthedocs +DOCSYAML + +# Building the bindings docs +mkdocs build + +# Pack the built site. +tar cvf ../../pulp-docs/pulp-docs-python-client-docs.tar ./site +popd +popd diff --git a/.github/workflows/scripts/install_ruby_client.sh b/.github/workflows/scripts/install_ruby_client.sh new file mode 100755 index 0000000..665b112 --- /dev/null +++ b/.github/workflows/scripts/install_ruby_client.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -mveuo pipefail + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +source .github/workflows/scripts/utils.sh + +PULP_URL="${PULP_URL:-https://pulp}" +export PULP_URL +PULP_API_ROOT="${PULP_API_ROOT:-/pulp/}" +export PULP_API_ROOT + +REPORTED_STATUS="$(pulp status)" +REPORTED_VERSION="$(echo "$REPORTED_STATUS" | jq --arg plugin "pulp-docs" -r '.versions[] | select(.component == $plugin) | .version')" +VERSION="$(echo "$REPORTED_VERSION" | python -c 'from packaging.version import Version; print(Version(input()))')" + +pushd ../pulp-openapi-generator +rm -rf pulp_docs-client + +if pulp debug has-plugin --name "core" --specifier ">=3.44.0.dev" +then + curl --fail-with-body -k -o api.json "${PULP_URL}${PULP_API_ROOT}api/v3/docs/api.json?bindings&component=pulp-docs" + USE_LOCAL_API_JSON=1 ./generate.sh pulp_docs ruby "$VERSION" +else + ./generate.sh pulp_docs ruby "$VERSION" +fi + +pushd pulp_docs-client +gem build pulp_docs_client +gem install --both "./pulp_docs_client-$VERSION.gem" +tar cvf ../../pulp-docs/pulp-docs-ruby-client.tar "./pulp_docs_client-$VERSION.gem" +popd +popd diff --git a/.github/workflows/scripts/publish_client_gem.sh b/.github/workflows/scripts/publish_client_gem.sh new file mode 100755 index 0000000..48a5439 --- /dev/null +++ b/.github/workflows/scripts/publish_client_gem.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -euv + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +VERSION="$1" + +if [[ -z "$VERSION" ]]; then + echo "No version specified." + exit 1 +fi + +RESPONSE="$(curl --write-out '%{http_code}' --silent --output /dev/null "https://rubygems.org/gems/pulp_docs_client/versions/$VERSION")" + +if [ "$RESPONSE" == "200" ]; +then + echo "pulp-docs client $VERSION has already been released. Skipping." + exit +fi + +mkdir -p ~/.gem +touch ~/.gem/credentials +echo "--- +:rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials +sudo chmod 600 ~/.gem/credentials +gem push "pulp_docs_client-${VERSION}.gem" diff --git a/.github/workflows/scripts/publish_client_pypi.sh b/.github/workflows/scripts/publish_client_pypi.sh new file mode 100755 index 0000000..671cdbe --- /dev/null +++ b/.github/workflows/scripts/publish_client_pypi.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -euv + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")/../../.." + +VERSION="$1" + +if [[ -z "$VERSION" ]]; then + echo "No version specified." + exit 1 +fi + +RESPONSE="$(curl --write-out '%{http_code}' --silent --output /dev/null "https://pypi.org/project/pulp-docs-client/$VERSION/")" + +if [ "$RESPONSE" == "200" ]; +then + echo "pulp-docs client $VERSION has already been released. Skipping." + exit +fi + +twine upload -u __token__ -p "$PYPI_API_TOKEN" \ +"dist/pulp_docs_client-$VERSION-py3-none-any.whl" \ +"dist/pulp_docs-client-$VERSION.tar.gz" \ +; diff --git a/.github/workflows/scripts/publish_docs.sh b/.github/workflows/scripts/publish_docs.sh new file mode 100755 index 0000000..55d1257 --- /dev/null +++ b/.github/workflows/scripts/publish_docs.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -euv + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")/../../.." + +mkdir ~/.ssh +touch ~/.ssh/pulp-infra +chmod 600 ~/.ssh/pulp-infra +echo "$PULP_DOCS_KEY" > ~/.ssh/pulp-infra + +echo "docs.pulpproject.org,8.43.85.236 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGXG+8vjSQvnAkq33i0XWgpSrbco3rRqNZr0SfVeiqFI7RN/VznwXMioDDhc+hQtgVhd6TYBOrV07IMcKj+FAzg=" >> ~/.ssh/known_hosts +chmod 644 ~/.ssh/known_hosts + +export PYTHONUNBUFFERED=1 +export DJANGO_SETTINGS_MODULE=pulpcore.app.settings +export PULP_SETTINGS=$PWD/.ci/ansible/settings/settings.py +export WORKSPACE=$PWD + +# start the ssh agent +eval "$(ssh-agent -s)" +ssh-add ~/.ssh/pulp-infra + +python3 .github/workflows/scripts/docs-publisher.py --build-type "$1" --branch "$2" + +if [[ "$GITHUB_WORKFLOW" == "Pulp-Docs changelog update" ]]; then + # Do not build bindings docs on changelog update + exit +fi + +mkdir -p ../pulp-docs-bindings +tar -xvf pulp-docs-python-client-docs.tar --directory ../pulp-docs-bindings +pushd ../pulp-docs-bindings + +# publish to docs.pulpproject.org/pulp_docs_client +rsync -avzh site/ doc_builder_pulp_docs@docs.pulpproject.org:/var/www/docs.pulpproject.org/pulp_docs_client/ + +# publish to docs.pulpproject.org/pulp_docs_client/en/{release} +rsync -avzh site/ doc_builder_pulp_docs@docs.pulpproject.org:/var/www/docs.pulpproject.org/pulp_docs_client/en/"$2" +popd diff --git a/.github/workflows/scripts/publish_plugin_pypi.sh b/.github/workflows/scripts/publish_plugin_pypi.sh new file mode 100755 index 0000000..b5ec501 --- /dev/null +++ b/.github/workflows/scripts/publish_plugin_pypi.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -euv + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +VERSION="$1" + +if [[ -z "$VERSION" ]]; then + echo "No version specified." + exit 1 +fi + +RESPONSE="$(curl --write-out '%{http_code}' --silent --output /dev/null "https://pypi.org/project/pulp-docs/$VERSION/")" + +if [ "$RESPONSE" == "200" ]; +then + echo "pulp-docs $VERSION has already been released. Skipping." + exit +fi + +twine upload -u __token__ -p "$PYPI_API_TOKEN" \ +"dist/pulp_docs-$VERSION-py3-none-any.whl" \ +"dist/pulp-docs-$VERSION.tar.gz" \ +; diff --git a/.github/workflows/scripts/push_branch_and_tag_to_github.sh b/.github/workflows/scripts/push_branch_and_tag_to_github.sh new file mode 100755 index 0000000..4e864b5 --- /dev/null +++ b/.github/workflows/scripts/push_branch_and_tag_to_github.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -eu + +BRANCH_NAME="$(echo "$GITHUB_REF" | sed -rn 's/refs\/heads\/(.*)/\1/p')" + +remote_repo="https://pulpbot:${RELEASE_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + +git push "${remote_repo}" "$BRANCH_NAME" "$1" diff --git a/.github/workflows/scripts/release.sh b/.github/workflows/scripts/release.sh new file mode 100755 index 0000000..9525f22 --- /dev/null +++ b/.github/workflows/scripts/release.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -eu -o pipefail + +BRANCH=$(git branch --show-current) + +if ! [[ "${BRANCH}" =~ ^[0-9]+\.[0-9]+$ ]] +then + echo ERROR: This is not a release branch! + exit 1 +fi + +NEW_VERSION="$(bump2version --dry-run --list release | sed -ne 's/^new_version=//p')" +echo "Release ${NEW_VERSION}" + +if ! [[ "${NEW_VERSION}" == "${BRANCH}"* ]] +then + echo ERROR: Version does not match release branch + exit 1 +fi + +towncrier build --yes --version "${NEW_VERSION}" +bump2version release --commit --message "Release {new_version}" --tag --tag-name "{new_version}" --tag-message "Release {new_version}" --allow-dirty +bump2version patch --commit + +git push origin "${BRANCH}" "${NEW_VERSION}" diff --git a/.github/workflows/scripts/script.sh b/.github/workflows/scripts/script.sh new file mode 100755 index 0000000..b9a1a53 --- /dev/null +++ b/.github/workflows/scripts/script.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env bash +# coding=utf-8 + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -mveuo pipefail + +# make sure this script runs at the repo root +cd "$(dirname "$(realpath -e "$0")")"/../../.. + +source .github/workflows/scripts/utils.sh + +export POST_SCRIPT=$PWD/.github/workflows/scripts/post_script.sh +export POST_DOCS_TEST=$PWD/.github/workflows/scripts/post_docs_test.sh +export FUNC_TEST_SCRIPT=$PWD/.github/workflows/scripts/func_test_script.sh + +# Needed for both starting the service and building the docs. +# Gets set in .github/settings.yml, but doesn't seem to inherited by +# this script. +export DJANGO_SETTINGS_MODULE=pulpcore.app.settings +export PULP_SETTINGS=$PWD/.ci/ansible/settings/settings.py + +export PULP_URL="https://pulp" + +if [[ "$TEST" = "docs" ]]; then + if [[ "$GITHUB_WORKFLOW" == "Pulp-Docs CI" ]]; then + towncrier build --yes --version 4.0.0.ci + fi + cd docs + make PULP_URL="$PULP_URL" diagrams html + tar -cvf docs.tar ./_build + cd .. + + if [ -f "$POST_DOCS_TEST" ]; then + source "$POST_DOCS_TEST" + fi + exit +fi + +if [[ "$TEST" = "new_docs" ]]; then + pip install --user git+https://github.com/pulp/pulp-docs + pulp-docs build +fi + +REPORTED_STATUS="$(pulp status)" + +echo "machine pulp +login admin +password password +" | cmd_user_stdin_prefix bash -c "cat >> ~pulp/.netrc" +# Some commands like ansible-galaxy specifically require 600 +cmd_prefix bash -c "chmod 600 ~pulp/.netrc" + +# Generate and install binding +pushd ../pulp-openapi-generator +if pulp debug has-plugin --name "core" --specifier ">=3.44.0.dev" +then + # Use app_label to generate api.json and package to produce the proper package name. + + if [ "$(jq -r '.domain_enabled' <<<"$REPORTED_STATUS")" = "true" ] + then + # Workaround: Domains are not supported by the published bindings. + # Generate new bindings for all packages. + for item in $(jq -r '.versions[] | tojson' <<<"$REPORTED_STATUS") + do + echo $item + COMPONENT="$(jq -r '.component' <<<"$item")" + VERSION="$(jq -r '.version' <<<"$item")" + MODULE="$(jq -r '.module' <<<"$item")" + PACKAGE="${MODULE%%.*}" + curl --fail-with-body -k -o api.json "${PULP_URL}${PULP_API_ROOT}api/v3/docs/api.json?bindings&component=$COMPONENT" + USE_LOCAL_API_JSON=1 ./generate.sh "${PACKAGE}" python "${VERSION}" + cmd_prefix pip3 install "/root/pulp-openapi-generator/${PACKAGE}-client" + sudo rm -rf "./${PACKAGE}-client" + done + else + # Sadly: Different pulpcore-versions aren't either... + for item in $(jq -r '.versions[]| select(.component!="pulp-docs")| tojson' <<<"$REPORTED_STATUS") + do + echo $item + COMPONENT="$(jq -r '.component' <<<"$item")" + VERSION="$(jq -r '.version' <<<"$item")" + MODULE="$(jq -r '.module' <<<"$item")" + PACKAGE="${MODULE%%.*}" + curl --fail-with-body -k -o api.json "${PULP_URL}${PULP_API_ROOT}api/v3/docs/api.json?bindings&component=$COMPONENT" + USE_LOCAL_API_JSON=1 ./generate.sh "${PACKAGE}" python "${VERSION}" + cmd_prefix pip3 install "/root/pulp-openapi-generator/${PACKAGE}-client" + sudo rm -rf "./${PACKAGE}-client" + done + fi +else + # Infer the client name from the package name by replacing "-" with "_". + # Use the component to infer the package name on older versions of pulpcore. + + if [ "$(echo "$REPORTED_STATUS" | jq -r '.domain_enabled')" = "true" ] + then + # Workaround: Domains are not supported by the published bindings. + # Generate new bindings for all packages. + for item in $(echo "$REPORTED_STATUS" | jq -r '.versions[]|(.package // ("pulp_" + .component)|sub("pulp_core"; "pulpcore"))|sub("-"; "_")') + do + ./generate.sh "${item}" python + cmd_prefix pip3 install "/root/pulp-openapi-generator/${item}-client" + sudo rm -rf "./${item}-client" + done + else + # Sadly: Different pulpcore-versions aren't either... + for item in $(echo "$REPORTED_STATUS" | jq -r '.versions[]|select(.component!="pulp-docs")|(.package // ("pulp_" + .component)|sub("pulp_core"; "pulpcore"))|sub("-"; "_")') + do + ./generate.sh "${item}" python + cmd_prefix pip3 install "/root/pulp-openapi-generator/${item}-client" + sudo rm -rf "./${item}-client" + done + fi +fi +popd + +# At this point, this is a safeguard only, so let's not make too much fuzz about the old status format. +echo "$REPORTED_STATUS" | jq -r '.versions[]|select(.package)|(.package|sub("_"; "-")) + "-client==" + .version' > bindings_requirements.txt +cmd_stdin_prefix bash -c "cat > /tmp/unittest_requirements.txt" < unittest_requirements.txt +cmd_stdin_prefix bash -c "cat > /tmp/functest_requirements.txt" < functest_requirements.txt +cmd_stdin_prefix bash -c "cat > /tmp/bindings_requirements.txt" < bindings_requirements.txt +cmd_prefix pip3 install -r /tmp/unittest_requirements.txt -r /tmp/functest_requirements.txt -r /tmp/bindings_requirements.txt + +CERTIFI=$(cmd_prefix python3 -c 'import certifi; print(certifi.where())') +cmd_prefix bash -c "cat /etc/pulp/certs/pulp_webserver.crt >> '$CERTIFI'" + +# check for any uncommitted migrations +echo "Checking for uncommitted migrations..." +cmd_user_prefix bash -c "django-admin makemigrations pulp-docs --check --dry-run" + +# Run unit tests. +cmd_user_prefix bash -c "PULP_DATABASES__default__USER=postgres pytest -v -r sx --color=yes --suppress-no-test-exit-code -p no:pulpcore --pyargs pulp_docs.tests.unit" +# Run functional tests +if [[ "$TEST" == "performance" ]]; then + if [[ -z ${PERFORMANCE_TEST+x} ]]; then + cmd_user_prefix bash -c "pytest -vv -r sx --color=yes --suppress-no-test-exit-code --capture=no --durations=0 --pyargs pulp_docs.tests.performance" + else + cmd_user_prefix bash -c "pytest -vv -r sx --color=yes --suppress-no-test-exit-code --capture=no --durations=0 --pyargs pulp_docs.tests.performance.test_${PERFORMANCE_TEST}" + fi + exit +fi + +if [ -f "$FUNC_TEST_SCRIPT" ]; then + source "$FUNC_TEST_SCRIPT" +else + if [[ "$GITHUB_WORKFLOW" =~ "Nightly" ]] + then + cmd_user_prefix bash -c "pytest -v -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_docs.tests.functional -m parallel -n 8 --nightly" + cmd_user_prefix bash -c "pytest -v -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_docs.tests.functional -m 'not parallel' --nightly" + else + cmd_user_prefix bash -c "pytest -v -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_docs.tests.functional -m parallel -n 8" + cmd_user_prefix bash -c "pytest -v -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_docs.tests.functional -m 'not parallel'" + fi +fi + +if [ -f "$POST_SCRIPT" ]; then + source "$POST_SCRIPT" +fi diff --git a/.github/workflows/scripts/secrets.py b/.github/workflows/scripts/secrets.py new file mode 100755 index 0000000..af5ef74 --- /dev/null +++ b/.github/workflows/scripts/secrets.py @@ -0,0 +1,14 @@ +import json +import os +import sys + +secrets = json.loads(sys.argv[1]) +for key, value in secrets.items(): + print(f"Setting {key} ...") + lines = len(value.split("\n")) + if lines > 1: + os.system(f"/bin/bash -c \"echo '{key}<> $GITHUB_ENV\"") + os.system(f"/bin/bash -c \"echo '{value}' >> $GITHUB_ENV\"") + os.system("/bin/bash -c \"echo 'EOF' >> $GITHUB_ENV\"") + else: + os.system(f"/bin/bash -c \"echo '{key}={value}' >> $GITHUB_ENV\"") diff --git a/.github/workflows/scripts/stage-changelog-for-default-branch.py b/.github/workflows/scripts/stage-changelog-for-default-branch.py new file mode 100755 index 0000000..97254e1 --- /dev/null +++ b/.github/workflows/scripts/stage-changelog-for-default-branch.py @@ -0,0 +1,70 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import argparse +import os +import textwrap + +from git import Repo +from git.exc import GitCommandError + + +helper = textwrap.dedent( + """\ + Stage the changelog for a release on main branch. + + Example: + $ python .github/workflows/scripts/stage-changelog-for-default-branch.py 3.4.0 + + """ +) + +parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description=helper) + +parser.add_argument( + "release_version", + type=str, + help="The version string for the release.", +) + +args = parser.parse_args() + +release_version_arg = args.release_version + +release_path = os.path.dirname(os.path.abspath(__file__)) +plugin_path = release_path.split("/.github")[0] + +if not release_version_arg.endswith(".0"): + os._exit(os.system("python .ci/scripts/changelog.py")) + +print(f"\n\nRepo path: {plugin_path}") +repo = Repo(plugin_path) + +changelog_commit = None +# Look for a commit with the requested release version +for commit in repo.iter_commits(): + if f"{release_version_arg} changelog" == commit.message.split("\n")[0]: + changelog_commit = commit + break + if f"Add changelog for {release_version_arg}" == commit.message.split("\n")[0]: + changelog_commit = commit + break + +if not changelog_commit: + raise RuntimeError("Changelog commit for {release_version_arg} was not found.") + +git = repo.git +git.stash() +git.checkout("origin/main") +try: + git.cherry_pick(changelog_commit.hexsha) +except GitCommandError: + git.add("CHANGES/") + # Don't try opening an editor for the commit message + with git.custom_environment(GIT_EDITOR="true"): + git.cherry_pick("--continue") +git.reset("origin/main") diff --git a/.github/workflows/scripts/update_backport_labels.py b/.github/workflows/scripts/update_backport_labels.py new file mode 100755 index 0000000..01fa835 --- /dev/null +++ b/.github/workflows/scripts/update_backport_labels.py @@ -0,0 +1,59 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +import requests +import yaml +import random +import os + + +def random_color(): + """Generates a random 24-bit number in hex""" + color = random.randrange(0, 2**24) + return format(color, "06x") + + +session = requests.Session() +token = os.getenv("GITHUB_TOKEN") + +headers = { + "Authorization": f"token {token}", + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", +} +session.headers.update(headers) + +# get all labels from the repository's current state +response = session.get("https://api.github.com/repos/pulp/pulp-docs/labels", headers=headers) +assert response.status_code == 200 +old_labels = set([x["name"] for x in response.json() if x["name"].startswith("backport-")]) + +# get list of branches from template_config.yml +with open("./template_config.yml", "r") as f: + plugin_template = yaml.safe_load(f) +branches = set(plugin_template["supported_release_branches"]) +latest_release_branch = plugin_template["latest_release_branch"] +if latest_release_branch is not None: + branches.add(latest_release_branch) +new_labels = {"backport-" + x for x in branches} + +# delete old labels that are not in new labels +for label in old_labels.difference(new_labels): + response = session.delete( + f"https://api.github.com/repos/pulp/pulp_docs/labels/{label}", headers=headers + ) + assert response.status_code == 204 + +# create new labels that are not in old labels +for label in new_labels.difference(old_labels): + color = random_color() + response = session.post( + "https://api.github.com/repos/pulp/pulp_docs/labels", + headers=headers, + json={"name": label, "color": color}, + ) + assert response.status_code == 201 diff --git a/.github/workflows/scripts/utils.sh b/.github/workflows/scripts/utils.sh new file mode 100755 index 0000000..b63d0a6 --- /dev/null +++ b/.github/workflows/scripts/utils.sh @@ -0,0 +1,30 @@ +# This file is meant to be sourced by ci-scripts + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +PULP_CI_CONTAINER=pulp + +# Run a command +cmd_prefix() { + docker exec "$PULP_CI_CONTAINER" "$@" +} + +# Run a command as the limited pulp user +cmd_user_prefix() { + docker exec -u pulp "$PULP_CI_CONTAINER" "$@" +} + +# Run a command, and pass STDIN +cmd_stdin_prefix() { + docker exec -i "$PULP_CI_CONTAINER" "$@" +} + +# Run a command as the lmited pulp user, and pass STDIN +cmd_user_stdin_prefix() { + docker exec -i -u pulp "$PULP_CI_CONTAINER" "$@" +} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..a8c09ff --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,169 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +--- +name: "Test" +on: + workflow_call: + +defaults: + run: + working-directory: "pulp-docs" + +jobs: + test: + runs-on: "ubuntu-latest" + strategy: + fail-fast: false + matrix: + env: + - TEST: pulp + - TEST: docs + - TEST: new_docs + - TEST: lowerbounds + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + path: "pulp-docs" + + - uses: "actions/checkout@v4" + with: + fetch-depth: 1 + repository: "pulp/pulp-openapi-generator" + path: "pulp-openapi-generator" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - uses: "actions/download-artifact@v3" + with: + name: "plugin_package" + path: "pulp-docs/dist/" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install towncrier twine wheel httpie docker netaddr boto3 ansible mkdocs + echo "HTTPIE_CONFIG_DIR=$GITHUB_WORKSPACE/pulp-docs/.ci/assets/httpie/" >> $GITHUB_ENV + echo ::endgroup:: + + - name: "Set environment variables" + run: | + echo "TEST=${{ matrix.env.TEST }}" >> $GITHUB_ENV + + - name: "Before Install" + run: | + .github/workflows/scripts/before_install.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + - uses: ruby/setup-ruby@v1 + if: ${{ env.TEST == 'pulp' }} + with: + ruby-version: "2.6" + + - name: "Install" + run: | + .github/workflows/scripts/install.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + + - name: "Before Script" + run: | + .github/workflows/scripts/before_script.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + REDIS_DISABLED: "${{ contains('', matrix.env.TEST) }}" + + - name: "Install Python client" + run: | + .github/workflows/scripts/install_python_client.sh + shell: "bash" + - name: "Install Ruby client" + if: "${{ env.TEST == 'pulp' }}" + run: | + .github/workflows/scripts/install_ruby_client.sh + shell: "bash" + + - name: "Script" + run: | + .github/workflows/scripts/script.sh + shell: "bash" + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + + - name: "Extract Deprecations from Logs" + run: | + docker logs pulp 2>&1 | grep -i pulpcore.deprecation | tee deprecations-${{ matrix.env.TEST }}.txt + + - name: "Upload Deprecations" + uses: actions/upload-artifact@v3 + with: + name: "deprecations" + path: "pulp-docs/deprecations-${{ matrix.env.TEST }}.txt" + if-no-files-found: "error" + retention-days: 5 + - name: Upload python client packages + if: ${{ env.TEST == 'pulp' }} + uses: actions/upload-artifact@v3 + with: + name: "python-client.tar" + path: "pulp-docs/pulp-docs-python-client.tar" + if-no-files-found: "error" + retention-days: 5 + + - name: Upload python client docs + if: ${{ env.TEST == 'pulp' }} + uses: actions/upload-artifact@v3 + with: + name: "python-client-docs.tar" + path: "pulp-docs/pulp-docs-python-client-docs.tar" + if-no-files-found: "error" + retention-days: 5 + - name: Upload Ruby client + if: ${{ env.TEST == 'pulp' }} + uses: actions/upload-artifact@v3 + with: + name: "ruby-client.tar" + path: "pulp-docs/pulp-docs-ruby-client.tar" + if-no-files-found: "error" + retention-days: 5 + - name: Upload built docs + if: ${{ env.TEST == 'docs' }} + uses: actions/upload-artifact@v3 + with: + name: "docs.tar" + path: "pulp-docs/docs/docs.tar" + + - name: "Logs" + if: always() + run: | + echo "Need to debug? Please check: https://github.com/marketplace/actions/debugging-with-tmate" + http --timeout 30 --check-status --pretty format --print hb "https://pulp${PULP_API_ROOT}api/v3/status/" || true + docker images || true + docker ps -a || true + docker logs pulp || true + docker exec pulp ls -latr /etc/yum.repos.d/ || true + docker exec pulp cat /etc/yum.repos.d/* || true + docker exec pulp bash -c "pip3 list && pip3 install pipdeptree && pipdeptree" diff --git a/.github/workflows/update-labels.yml b/.github/workflows/update-labels.yml new file mode 100644 index 0000000..a83d979 --- /dev/null +++ b/.github/workflows/update-labels.yml @@ -0,0 +1,39 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + + +--- +name: "Pulp-Docs Update Labels" +on: + push: + branches: + - "main" + paths: + - "template_config.yml" + +jobs: + update_backport_labels: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + - name: "Configure Git with pulpbot name and email" + run: | + git config --global user.name 'pulpbot' + git config --global user.email 'pulp-infra@redhat.com' + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install requests pyyaml + echo ::endgroup:: + - uses: "actions/checkout@v4" + - name: "Update labels" + run: | + python3 .github/workflows/scripts/update_backport_labels.py + env: + GITHUB_TOKEN: "${{ secrets.RELEASE_TOKEN }}" diff --git a/.github/workflows/update_ci.yml b/.github/workflows/update_ci.yml new file mode 100644 index 0000000..a012f5c --- /dev/null +++ b/.github/workflows/update_ci.yml @@ -0,0 +1,72 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + + +--- +name: "Pulp-Docs CI Update" +on: + schedule: + # * is a special character in YAML so you have to quote this string + # runs at 2:30 UTC every Sunday + - cron: '30 2 * * 0' + workflow_dispatch: + +jobs: + update: + runs-on: "ubuntu-latest" + + strategy: + fail-fast: false + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + repository: "pulp/plugin_template" + path: "plugin_template" + + - uses: "actions/setup-python@v4" + with: + python-version: "3.11" + + - name: "Install python dependencies" + run: | + echo ::group::PYDEPS + pip install gitpython requests packaging jinja2 pyyaml + echo ::endgroup:: + + - name: "Configure Git with pulpbot name and email" + run: | + git config --global user.name 'pulpbot' + git config --global user.email 'pulp-infra@redhat.com' + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + path: "pulp-docs" + ref: "main" + + - name: "Run update" + working-directory: "pulp-docs" + run: | + ../plugin_template/scripts/update_ci.sh + + - name: "Create Pull Request for CI files" + uses: "peter-evans/create-pull-request@v6" + with: + token: "${{ secrets.RELEASE_TOKEN }}" + path: "pulp-docs" + committer: "pulpbot " + author: "pulpbot " + title: "Update CI files for branch main" + body: "" + branch: "update-ci/main" + base: "main" + commit-message: | + Update CI files + + [noissue] + delete-branch: true diff --git a/CHANGES/.TEMPLATE.rst b/CHANGES/.TEMPLATE.rst new file mode 100644 index 0000000..49c2305 --- /dev/null +++ b/CHANGES/.TEMPLATE.rst @@ -0,0 +1,47 @@ +{% if render_title %} +{% if versiondata.name %} +{{ versiondata.name }} {{ versiondata.version }} ({{ versiondata.date }}) +{{ top_underline * ((versiondata.name + versiondata.version + versiondata.date)|length + 4)}} +{% else %} +{{ versiondata.version }} ({{ versiondata.date }}) +{{ top_underline * ((versiondata.version + versiondata.date)|length + 3)}} +{% endif %} +{% endif %} +{% for section, _ in sections.items() %} +{% set underline = underlines[0] %}{% if section %}{{section}} +{{ underline * section|length }}{% set underline = underlines[1] %} + +{% endif %} + +{% if sections[section] %} +{% for category, val in definitions.items() if category in sections[section]%} +{{ definitions[category]['name'] }} +{{ underline * definitions[category]['name']|length }} + +{% if definitions[category]['showcontent'] %} +{% for text, values in sections[section][category].items() %} +- {{ text }} + {{ values|join(',\n ') }} +{% endfor %} + +{% else %} +- {{ sections[section][category]['']|join(', ') }} + +{% endif %} +{% if sections[section][category]|length == 0 %} +No significant changes. + +{% else %} +{% endif %} + +{% endfor %} +{% else %} +No significant changes. + + +{% endif %} +{% endfor %} +---- + + + diff --git a/CHANGES/.gitignore b/CHANGES/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/CHANGES/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/functest_requirements.txt b/functest_requirements.txt new file mode 100644 index 0000000..e70c0b4 --- /dev/null +++ b/functest_requirements.txt @@ -0,0 +1 @@ +pytest<8 diff --git a/lint_requirements.txt b/lint_requirements.txt new file mode 100644 index 0000000..58cea11 --- /dev/null +++ b/lint_requirements.txt @@ -0,0 +1,13 @@ +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_docs' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +# python packages handy for developers, but not required by pulp +black==23.12.1 +check-manifest +flake8 +flake8-black +yamllint diff --git a/template_config.yml b/template_config.yml new file mode 100644 index 0000000..3aaf04e --- /dev/null +++ b/template_config.yml @@ -0,0 +1,72 @@ +# This config represents the latest values used when running the plugin-template. Any settings that +# were not present before running plugin-template have been added with their default values. + +# generated with plugin_template@2021.08.26-321-g24de2b1-dirty + +api_root: /pulp/ +black: true +check_commit_message: true +check_gettext: true +check_manifest: true +check_stray_pulpcore_imports: true +ci_base_image: ghcr.io/pulp/pulp-ci-centos9 +ci_env: {} +ci_trigger: '{pull_request: {branches: [''*'']}}' +ci_update_docs: false +cli_package: pulp-cli +cli_repo: https://github.com/pulp/pulp-cli.git +core_import_allowed: [] +deploy_client_to_pypi: true +deploy_client_to_rubygems: true +deploy_to_pypi: true +disabled_redis_runners: [] +doc_requirements_from_pulpcore: false +docker_fixtures: false +docs_test: true +extra_docs_requirements: [] +flake8: true +flake8_ignore: [] +github_org: pulp +issue_tracker: github +kanban: true +latest_release_branch: null +lint_requirements: true +noissue_marker: '[noissue]' +parallel_test_workers: 8 +plugin_app_label: pulp-docs +plugin_default_branch: main +plugin_name: pulp-docs +plugins: +- app_label: pulp-docs + name: pulp-docs +post_job_template: null +pre_job_template: null +publish_docs_to_pulpprojectdotorg: false +pulp_env: {} +pulp_env_azure: {} +pulp_env_gcp: {} +pulp_env_s3: {} +pulp_scheme: https +pulp_settings: null +pulp_settings_azure: null +pulp_settings_gcp: null +pulp_settings_s3: null +pydocstyle: true +release_email: pulp-infra@redhat.com +release_user: pulpbot +stalebot: true +stalebot_days_until_close: 30 +stalebot_days_until_stale: 90 +stalebot_limit_to_pulls: true +supported_release_branches: [] +sync_ci: true +test_azure: false +test_cli: false +test_deprecations: true +test_gcp: false +test_lowerbounds: true +test_performance: false +test_reroute: true +test_s3: false +use_issue_template: true + diff --git a/unittest_requirements.txt b/unittest_requirements.txt new file mode 100644 index 0000000..e70c0b4 --- /dev/null +++ b/unittest_requirements.txt @@ -0,0 +1 @@ +pytest<8