diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2f4ff900d8..88cbda4414 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,5 @@ updates: directory: "/" schedule: interval: "weekly" + cooldown: + default-days: 4 diff --git a/.github/workflows/build-devel-docs.yaml b/.github/workflows/build-devel-docs.yaml index 115908c88b..d0c77b3784 100644 --- a/.github/workflows/build-devel-docs.yaml +++ b/.github/workflows/build-devel-docs.yaml @@ -5,6 +5,9 @@ name: Scheduled build for devel docs # Run at 05:22 daily - cron: '22 5 * * *' +permissions: + contents: read + jobs: build-package-docs: name: 📝 Build diff --git a/.github/workflows/build-latest-docs.yaml b/.github/workflows/build-latest-docs.yaml index 0427c022c7..d89cdd28ce 100644 --- a/.github/workflows/build-latest-docs.yaml +++ b/.github/workflows/build-latest-docs.yaml @@ -5,6 +5,9 @@ name: Scheduled build for latest docs # Run at 05:41 on Monday - cron: '41 5 * * 1' +permissions: + contents: read + jobs: build-package-docs: name: 📝 Build diff --git a/.github/workflows/build-package-docs.yaml b/.github/workflows/build-package-docs.yaml index 566c1f7721..5bc73e4983 100644 --- a/.github/workflows/build-package-docs.yaml +++ b/.github/workflows/build-package-docs.yaml @@ -51,6 +51,9 @@ name: Build and deploy docs - production - test +permissions: + contents: read + jobs: build-package-docs: name: 📝 Build diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 58ab8908fa..93ee76ba72 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,6 +16,9 @@ name: Ansible Docsite CI - ready_for_review # used in PRs created from GitHub Actions workflows workflow_dispatch: +permissions: + contents: read + jobs: nox: uses: ./.github/workflows/reusable-nox.yml diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index c2ad213f33..1fbd9905b4 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -3,7 +3,9 @@ # SPDX-License-Identifier: GPL-3.0-or-later "on": - pull_request_target: + # This workflow does not execute untrusted code from pull requests and all + # inputs are properly sanitized, + pull_request_target: # zizmor: ignore[dangerous-triggers] types: - opened # default - synchronize # default @@ -29,6 +31,9 @@ name: "Triage Issues and PRs" +permissions: + contents: read + jobs: label_prs: runs-on: ubuntu-latest @@ -48,6 +53,8 @@ jobs: private-key: ${{ secrets.BOT_APP_KEY }} - name: Checkout parent repository uses: actions/checkout@v5 + with: + persist-credentials: false - name: Install Python 3.12 uses: actions/setup-python@v6 with: diff --git a/.github/workflows/pip-compile-dev.yml b/.github/workflows/pip-compile-dev.yml index a828e9bdf5..c8a6cbd741 100644 --- a/.github/workflows/pip-compile-dev.yml +++ b/.github/workflows/pip-compile-dev.yml @@ -13,6 +13,9 @@ name: "Refresh dev dependencies" required: false type: string +permissions: + contents: read + jobs: refresh: strategy: @@ -71,4 +74,9 @@ jobs: python-versions: "${{ matrix.python-versions }}" reset-branch: "${{ inputs.reset-branch || false }}" labels: "${{ inputs.labels || 'no_backport,tooling' }}" - secrets: inherit + # Pass using inherit, as this seems to be the only possible way to access + # secrets defined in an enviornment when using nested workflows. + secrets: inherit # zizmor: ignore[secrets-inherit] + # secrets: + # BOT_APP_ID: "${{ secrets.BOT_APP_ID }}" + # BOT_APP_KEY: "${{ secrets.BOT_APP_KEY }}" diff --git a/.github/workflows/pip-compile-docs.yml b/.github/workflows/pip-compile-docs.yml index 4e6d44fce5..2ae80090eb 100644 --- a/.github/workflows/pip-compile-docs.yml +++ b/.github/workflows/pip-compile-docs.yml @@ -19,6 +19,9 @@ name: "Refresh docs build dependencies" required: false type: string +permissions: + contents: read + jobs: refresh: name: "Refresh docs build dependencies" @@ -33,4 +36,9 @@ jobs: reset-branch: "${{ inputs.reset-branch || false }}" labels: "${{ inputs.labels || 'doc builds,no_backport' }}" python-versions: "3.12" - secrets: inherit + # Pass using inherit, as this seems to be the only possible way to access + # secrets defined in an enviornment when using nested workflows. + secrets: inherit # zizmor: ignore[secrets-inherit] + # secrets: + # BOT_APP_ID: "${{ secrets.BOT_APP_ID }}" + # BOT_APP_KEY: "${{ secrets.BOT_APP_KEY }}" diff --git a/.github/workflows/release-porting-guide.yml b/.github/workflows/release-porting-guide.yml index 4c96d43829..5f99378829 100644 --- a/.github/workflows/release-porting-guide.yml +++ b/.github/workflows/release-porting-guide.yml @@ -12,6 +12,8 @@ on: description: >- Exact release version. For example, 12.1.0 required: true +permissions: + contents: read jobs: upload-porting-guide: @@ -40,6 +42,7 @@ jobs: uses: actions/checkout@v5 with: token: ${{ steps.create_token.outputs.token }} + persist-credentials: true # Needed to push to the repo - name: Check out ansible-build-data uses: actions/checkout@v5 @@ -47,6 +50,7 @@ jobs: repository: ansible-community/ansible-build-data ref: ${{ inputs.ansible-build-data-branch }} path: ansible-build-data + persist-credentials: false - name: Copy the RST file to the correct path run: >- diff --git a/.github/workflows/reusable-build-docs.yaml b/.github/workflows/reusable-build-docs.yaml index 0dd7b27725..ec190cde66 100644 --- a/.github/workflows/reusable-build-docs.yaml +++ b/.github/workflows/reusable-build-docs.yaml @@ -32,9 +32,6 @@ name: Build docs DOCS_BOT_TOKEN: required: true -env: - PACKAGE_VERSION: ${{ inputs.ansible-package-version }} - jobs: build-package-docs: runs-on: ubuntu-latest @@ -50,6 +47,7 @@ jobs: }} ref: ${{ inputs.repository-branch }} path: build-directory + persist-credentials: false - name: Setup nox uses: wntrblm/nox@2025.10.16 @@ -68,19 +66,22 @@ jobs: -c tests/requirements.txt working-directory: build-directory - - name: Set the VERSION variable - run: echo VERSION="${PACKAGE_VERSION}" >> "${GITHUB_ENV}" - - name: Build the Ansible community package docs - run: >- - make webdocs ${{ + env: + PACKAGE_VERSION: "${{ inputs.ansible-package-version }}" + run: | + # Clear PACKAGE_VERSION if it's set to devel + if [ "${PACKAGE_VERSION}" = "devel" ]; then + PACKAGE_VERSION="" + fi + make webdocs ANSIBLE_VERSION="${PACKAGE_VERSION}" ${{ inputs.generate-redirects && 'EXTRA_TAGS="-t redirects"' || '' - }} ANSIBLE_VERSION="${{ - env.PACKAGE_VERSION != 'devel' && env.PACKAGE_VERSION || '' - }}" + }} working-directory: build-directory/docs/docsite - name: Create a tarball with the build contents + env: + PACKAGE_VERSION: "${{ inputs.ansible-package-version }}" run: >- tar -czvf ansible-package-docs-html-"${PACKAGE_VERSION}"-"$(date '+%Y-%m-%d')"-${{ @@ -116,8 +117,10 @@ jobs: run: echo "TX_ID=$(date +%s)" >> "${GITHUB_ENV}" - name: Notify the DaWGs in Matrix + # FAIL_MESSAGE is trusted input so okay to inject here. + # zizmor: ignore[template-injection] run: | - curl -X PUT "${{ env.ROOM_URL }}/${TX_ID}" \ + curl -X PUT "${ROOM_URL}/${TX_ID}" \ -H "Authorization: Bearer ${{ secrets.DOCS_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ -d '{"msgtype": "m.text", "body": "${{ env.FAIL_MESSAGE }}"}' diff --git a/.github/workflows/reusable-deploy-docs.yaml b/.github/workflows/reusable-deploy-docs.yaml index 2dc41fb1ae..095fc5e34c 100644 --- a/.github/workflows/reusable-deploy-docs.yaml +++ b/.github/workflows/reusable-deploy-docs.yaml @@ -33,13 +33,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Log the workflow inputs if deployed + env: + deployment_environment: "${{ inputs.deployment-environment }}" + package_version: "${{ inputs.ansible-package-version }}" + owner: "${{ inputs.repository-owner }}" + branch: "${{ inputs.repository-branch }}" run: | { echo "## Deployment details :shipit:"; - echo "Publish to: ${{ inputs.deployment-environment }}"; - echo "Package version: ${{ inputs.ansible-package-version }}"; - echo "Owner: ${{ inputs.repository-owner }}"; - echo "Branch: ${{ inputs.repository-branch }}"; + echo "Publish to: ${deployment_environment}"; + echo "Package version: ${package_version}"; + echo "Owner: ${owner}"; + echo "Branch: ${branch}"; } >> "${GITHUB_STEP_SUMMARY}" deploy-package-docs: diff --git a/.github/workflows/reusable-nox.yml b/.github/workflows/reusable-nox.yml index c46f4a4552..08c1df6421 100644 --- a/.github/workflows/reusable-nox.yml +++ b/.github/workflows/reusable-nox.yml @@ -34,10 +34,14 @@ jobs: - session: "pip-compile" extra-args: "--check" python-versions: "3.12" + - session: "zizmor" + python-versions: "3.12" name: "Run nox ${{ matrix.session }} session" steps: - name: Check out repo uses: actions/checkout@v5 + with: + persist-credentials: false - name: Setup nox uses: wntrblm/nox@2025.10.16 with: @@ -46,7 +50,8 @@ jobs: run: | nox -e clone-core - name: "Run nox -e ${{ matrix.session }}" + # Using GHA expression interpolation is fine here, + # as we control all the inputs. + # zizmor: ignore[template-injection] run: | - # Using GHA expression interpolation is fine here, - # as we control all the inputs. nox -e "${{ matrix.session }}" -- ${{ matrix.extra-args }} diff --git a/.github/workflows/reusable-pip-compile.yml b/.github/workflows/reusable-pip-compile.yml index 5c03236a6d..078ed638e2 100644 --- a/.github/workflows/reusable-pip-compile.yml +++ b/.github/workflows/reusable-pip-compile.yml @@ -35,23 +35,21 @@ name: "Refresh pinned dependencies" python-versions: type: string required: true + +permissions: + contents: read + jobs: refresh: runs-on: ubuntu-latest environment: github-bot steps: - - name: Generate temp GITHUB_TOKEN - id: create_token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.BOT_APP_ID }} - private-key: ${{ secrets.BOT_APP_KEY }} - name: Check out repo uses: actions/checkout@v5 with: fetch-depth: 0 ref: "${{ inputs.base-branch }}" - token: "${{ steps.create_token.outputs.token }}" + persist-credentials: false - name: Fetch required contents of ansible-core run: | python docs/bin/clone-core.py @@ -82,9 +80,23 @@ jobs: env: # Ensure the latest pip version is used VIRTUALENV_DOWNLOAD: '1' - # + # nox-args is defined statically in the calling workflows and passing it + # as a shell variable presents quoting issues, so ignore zizmor error + # for now. + # zizmor: ignore[template-injection] run: | nox ${{ inputs.nox-args }} + - name: Generate temp GITHUB_TOKEN + id: create_token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.BOT_APP_ID }} + private-key: ${{ secrets.BOT_APP_KEY }} + # We could rely on the checkout action to persist the token in the + # repository config, but this way, we can prevent the previous steps + # from having unnecessary access. + - name: "Set up token authentication" + run: gh auth setup-git --force --hostname github.com - name: Push new dependency versions and create a PR env: GITHUB_TOKEN: ${{ steps.create_token.outputs.token }} diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 855a241a5a..7d4fd21337 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -11,6 +11,9 @@ name: Sync tags with ansible-core releases schedule: - cron: "0 * * * *" # Hourly +permissions: + contents: read # read-only because we use bot token to push + jobs: tag: runs-on: "ubuntu-latest" @@ -30,12 +33,14 @@ jobs: path: ansible-documentation fetch-depth: 0 token: "${{ steps.create_token.outputs.token }}" + persist-credentials: true - name: Check out core uses: actions/checkout@v5 with: repository: ansible/ansible path: ansible fetch-depth: 0 + persist-credentials: false - name: Setup nox uses: wntrblm/nox@2025.10.16 with: diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 0000000000..9dbdee8ad3 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,7 @@ +rules: + unpinned-uses: + config: + policies: + "wntrblm/nox": ref-pin + "re-actors/alls-green": ref-pin + "actions/*": ref-pin diff --git a/README.md b/README.md index ae2ba67ce8..8c5f80e498 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ The `nox` configuration also contains session to run automated docs checkers. If you want to view the generated HTML in your browser, you should build the documentation locally. See [Building the documentation locally](https://docs.ansible.com/ansible/latest/community/documentation_contributions.html#building-the-documentation-locally) for more information. -* Lint, type check, and format Python scripts in this repository. +* Lint, type check, and format Python scripts in this repository and lint the Github Actions workflows for syntax and security issues: ``` bash nox -s lint diff --git a/noxfile.py b/noxfile.py index 6ac33a3f13..053179f6ec 100644 --- a/noxfile.py +++ b/noxfile.py @@ -140,6 +140,15 @@ def actionlint(session: nox.Session) -> None: ) +@nox.session +def zizmor(session: nox.Session) -> None: + """ + Ren zizmor, a Github Actions security checker + """ + install(session, req="zizmor") + session.run("zizmor", "--persona=regular", ".github/workflows") + + @nox.session def lint(session: nox.Session): session.notify("typing") diff --git a/tests/zizmor.in b/tests/zizmor.in new file mode 100644 index 0000000000..d0c4882581 --- /dev/null +++ b/tests/zizmor.in @@ -0,0 +1 @@ +zizmor diff --git a/tests/zizmor.txt b/tests/zizmor.txt new file mode 100644 index 0000000000..9cbdbd2f23 --- /dev/null +++ b/tests/zizmor.txt @@ -0,0 +1,4 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile --universal --output-file tests/zizmor.txt tests/zizmor.in +zizmor==1.16.0 + # via -r tests/zizmor.in