diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..2f4ff900d88 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 868cf78cf63..a3a8e6834d8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,7 +4,9 @@ on: push: branches-ignore: - 'patchback/**' + - 'pip-compile/**' pull_request: + workflow_dispatch: jobs: docs_sanity_docs_build: @@ -54,3 +56,6 @@ jobs: - name: Run rstcheck Sanity run: | python tests/sanity.py rstcheck + + nox: + uses: ./.github/workflows/reusable-nox.yml diff --git a/.github/workflows/pip-compile-dev.yml b/.github/workflows/pip-compile-dev.yml new file mode 100644 index 00000000000..befde055072 --- /dev/null +++ b/.github/workflows/pip-compile-dev.yml @@ -0,0 +1,42 @@ +--- +name: "Refresh dev dependencies" +"on": + schedule: + # Weekly + - cron: "0 0 * * 0" + workflow_dispatch: + inputs: + base-branch: + required: false + type: string + pr-branch: + required: false + type: string + reset-branch: + type: boolean + default: false + push: + branches: + - devel + paths: + - .github/workflows/reusable-pip-compile.yml + - ".github/workflows/pip-compile-dev.yml" + - "tests/*.in" + +permissions: + pull-requests: write + contents: write + +jobs: + refresh: + name: "Refresh dev dependencies" + uses: ./.github/workflows/reusable-pip-compile.yml + with: + message: "ci: refresh dev dependencies" + base-branch: "${{ inputs.base-branch || 'devel' }}" + pr-branch: "${{ inputs.pr-branch || 'pip-compile/devel/dev' }}" + nox-args: >- + -e 'pip-compile-3.10(formatters)' + 'pip-compile-3.10(typing)' + 'pip-compile-3.10(static)' + reset-branch: "${{ inputs.reset-branch || false }}" diff --git a/.github/workflows/pip-compile-docs.yml b/.github/workflows/pip-compile-docs.yml new file mode 100644 index 00000000000..00585e79422 --- /dev/null +++ b/.github/workflows/pip-compile-docs.yml @@ -0,0 +1,39 @@ +--- +name: "Refresh docs build dependencies" +"on": + schedule: + # Weekly + - cron: "0 0 * * 0" + workflow_dispatch: + inputs: + base-branch: + required: false + type: string + pr-branch: + required: false + type: string + reset-branch: + type: boolean + default: false + push: + branches: + - devel + paths: + - .github/workflows/reusable-pip-compile.yml + - ".github/workflows/pip-compile-docs.yml" + - "tests/*.in" + +permissions: + pull-requests: write + contents: write + +jobs: + refresh: + name: "Refresh docs build dependencies" + uses: ./.github/workflows/reusable-pip-compile.yml + with: + message: "ci: refresh docs build dependencies" + base-branch: "${{ inputs.base-branch || 'devel' }}" + pr-branch: "${{ inputs.pr-branch || 'pip-compile/devel/docs' }}" + nox-args: "-e 'pip-compile-3.10(requirements)' 'pip-compile-3.10(requirements-relaxed)'" + reset-branch: "${{ inputs.reset-branch || false }}" diff --git a/.github/workflows/reusable-nox.yml b/.github/workflows/reusable-nox.yml new file mode 100644 index 00000000000..72baa63196e --- /dev/null +++ b/.github/workflows/reusable-nox.yml @@ -0,0 +1,30 @@ +--- +name: nox + +"on": + workflow_call: + +jobs: + nox: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - session: static + python-versions: "3.11" + - session: formatters_check + python-versions: "3.11" + - session: typing + python-versions: "3.11" + name: "Run nox ${{ matrix.session }} session" + steps: + - name: Check out repo + uses: actions/checkout@v3 + - name: Setup nox + uses: wntrblm/nox@2023.04.22 + with: + python-versions: "${{ matrix.python-versions }}" + - name: "Run nox -e ${{ matrix.session }}" + run: | + nox -e "${{ matrix.session }}" diff --git a/.github/workflows/reusable-pip-compile.yml b/.github/workflows/reusable-pip-compile.yml new file mode 100644 index 00000000000..9cb408a7ca9 --- /dev/null +++ b/.github/workflows/reusable-pip-compile.yml @@ -0,0 +1,120 @@ +--- +name: "Refresh pinned dependencies" + +"on": + workflow_call: + # GHA does not support anchors :( + # inputs: &inputs + inputs: + # Commit messae and PR title + message: + type: string + required: true + # Branch to create PR from + pr-branch: + type: string + required: true + # Branch to base PR on + base-branch: + type: string + required: true + # Nox session to call + nox-args: + type: string + required: true + # Files to commit + changed-files: + type: string + required: true + # Reset branch + reset-branch: + type: boolean + default: false + workflow_dispatch: + # inputs: *inputs + inputs: + message: + type: string + required: true + pr-branch: + type: string + required: true + base-branch: + type: string + required: true + nox-args: + type: string + required: true + changed-files: + default: "tests/*.txt" + type: string + required: true + reset-branch: + type: boolean + default: false + +permissions: + pull-requests: write + contents: write + +jobs: + refresh: + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: "${{ inputs.base-branch }}" + - name: Fetch required contents of ansible-core + run: | + python docs/bin/clone-core.py + - name: Set up nox + uses: wntrblm/nox@2023.04.22 + with: + python-versions: "3.9" + - name: Set up git committer + run: | + git config user.name "Github Actions" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + - name: "Use a branch named ${{ inputs.pr-branch }}" + id: branch + run: | + set -x + if git branch -r | grep "origin/${{ inputs.pr-branch }}"; then + echo "branch-exists=true" >> "${GITHUB_OUTPUT}" + git switch "${{ inputs.pr-branch }}" + ${{ inputs.reset-branch && 'git reset --hard' || 'git rebase' }} \ + "${{ inputs.base-branch }}" + else + echo "branch-exists=false" >> "${GITHUB_OUTPUT}" + git switch -c "${{ inputs.pr-branch }}" + fi + - name: "Run nox ${{ inputs.nox-args }}" + env: + # Ensure the latest pip version is used + VIRTUALENV_DOWNLOAD: '1' + run: | + nox ${{ inputs.nox-args }} + - name: Push new dependency versions and create a PR + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + run: | + set -x + git diff || : + git add ${{ inputs.changed-files }} + if git diff-index --quiet HEAD ${{ inputs.changed-files }}; then + echo "Nothing to do!" + exit + fi + + git commit -m "${{ inputs.message }}" + git push --force origin "${{ inputs.pr-branch }}" + if [ "${{ steps.branch.outputs.branch-exists }}" = "false" ] + then + gh pr create \ + --base "${{ inputs.base-branch }}" \ + --title "${{ inputs.message }}" \ + --body "" \ + --label dependency_update + fi diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 00000000000..c76db01ff4e --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,2 @@ +[isort] +profile = black diff --git a/.pip-tools.toml b/.pip-tools.toml new file mode 100644 index 00000000000..c1f6c7ad65a --- /dev/null +++ b/.pip-tools.toml @@ -0,0 +1,5 @@ +[tool.pip-tools] +resolver = "backtracking" +allow-unsafe = true +strip-extras = true +quiet = true diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 00000000000..266e930b741 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,76 @@ +import os +from pathlib import Path + +import nox + +LINT_FILES = ("hacking/pr_labeler/label.py", "noxfile.py") +PINNED = os.environ.get("PINNED", "true").lower() in {"1", "true"} +nox.options.sessions = ("lint",) + + +def install(session: nox.Session, *args, req: str, **kwargs): + if PINNED: + kwargs.setdefault("env", {})["PIP_CONSTRAINT"] = f"tests/{req}.txt" + session.install("-r", f"tests/{req}.in", *args, **kwargs) + + +@nox.session +def static(session: nox.Session): + """ + Run static checkers + """ + install(session, req="static") + session.run("ruff", *session.posargs, *LINT_FILES) + + +@nox.session +def formatters(session: nox.Session): + """ + Reformat code + """ + install(session, req="formatters") + session.run("isort", *session.posargs, *LINT_FILES) + session.run("black", *session.posargs, *LINT_FILES) + + +@nox.session +def formatters_check(session: nox.Session): + """ + Check code formatting without making changes + """ + install(session, req="formatters") + session.run("isort", "--check", *session.posargs, *LINT_FILES) + session.run("black", "--check", *session.posargs, *LINT_FILES) + + +@nox.session +def typing(session: nox.Session): + install(session, req="typing") + session.run("mypy", *session.posargs, *LINT_FILES) + + +@nox.session +def lint(session: nox.Session): + session.notify("static") + session.notify("formatters") + + +requirements_files = list( + {path.name.replace(".in", "") for path in Path("tests").glob("*in")} + - {"constraints", "constraints-base"} +) + + +@nox.session(name="pip-compile", python=["3.10"]) +@nox.parametrize(["req"], requirements_files, requirements_files) +def pip_compile(session: nox.Session, req: str): + # .pip-tools.toml was introduced in v7 + session.install("pip-tools >= 7") + # fmt: off + session.run( + "pip-compile", + "--upgrade", + "--output-file", f"tests/{req}.txt", + f"tests/{req}.in", + ) + # fmt: on diff --git a/tests/formatters.in b/tests/formatters.in new file mode 100644 index 00000000000..7559a405a0f --- /dev/null +++ b/tests/formatters.in @@ -0,0 +1,2 @@ +black +isort diff --git a/tests/formatters.txt b/tests/formatters.txt new file mode 100644 index 00000000000..6bc6dfadcbd --- /dev/null +++ b/tests/formatters.txt @@ -0,0 +1,22 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --allow-unsafe --output-file=tests/formatters.txt --strip-extras tests/formatters.in +# +black==23.7.0 + # via -r tests/formatters.in +click==8.1.6 + # via black +isort==5.12.0 + # via -r tests/formatters.in +mypy-extensions==1.0.0 + # via black +packaging==23.1 + # via black +pathspec==0.11.2 + # via black +platformdirs==3.10.0 + # via black +tomli==2.0.1 + # via black diff --git a/tests/static.in b/tests/static.in new file mode 100644 index 00000000000..af3ee576386 --- /dev/null +++ b/tests/static.in @@ -0,0 +1 @@ +ruff diff --git a/tests/static.txt b/tests/static.txt new file mode 100644 index 00000000000..998a51184f4 --- /dev/null +++ b/tests/static.txt @@ -0,0 +1,8 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --allow-unsafe --output-file=tests/static.txt --strip-extras tests/static.in +# +ruff==0.0.284 + # via -r tests/static.in diff --git a/tests/typing.in b/tests/typing.in new file mode 100644 index 00000000000..63112a0d90a --- /dev/null +++ b/tests/typing.in @@ -0,0 +1,3 @@ +-r ../hacking/pr_labeler/requirements.txt +mypy +nox diff --git a/tests/typing.txt b/tests/typing.txt new file mode 100644 index 00000000000..7ffa43ee932 --- /dev/null +++ b/tests/typing.txt @@ -0,0 +1,67 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --allow-unsafe --output-file=tests/typing.txt --strip-extras tests/typing.in +# +argcomplete==3.1.1 + # via nox +certifi==2023.7.22 + # via requests +cffi==1.15.1 + # via + # cryptography + # pynacl +charset-normalizer==3.2.0 + # via requests +click==8.1.6 + # via typer +codeowners==0.6.0 + # via -r tests/../hacking/pr_labeler/requirements.txt +colorlog==6.7.0 + # via nox +cryptography==41.0.3 + # via pyjwt +deprecated==1.2.14 + # via pygithub +distlib==0.3.7 + # via virtualenv +filelock==3.12.2 + # via virtualenv +idna==3.4 + # via requests +mypy==1.5.0 + # via -r tests/typing.in +mypy-extensions==1.0.0 + # via mypy +nox==2023.4.22 + # via -r tests/typing.in +packaging==23.1 + # via nox +platformdirs==3.10.0 + # via virtualenv +pycparser==2.21 + # via cffi +pygithub==1.59.1 + # via -r tests/../hacking/pr_labeler/requirements.txt +pyjwt==2.8.0 + # via pygithub +pynacl==1.5.0 + # via pygithub +requests==2.31.0 + # via pygithub +tomli==2.0.1 + # via mypy +typer==0.9.0 + # via -r tests/../hacking/pr_labeler/requirements.txt +typing-extensions==4.7.1 + # via + # codeowners + # mypy + # typer +urllib3==2.0.4 + # via requests +virtualenv==20.24.2 + # via nox +wrapt==1.15.0 + # via deprecated