Matrix Docker Ansible eploy
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

162 рядки
5.3 KiB

  1. # SPDX-FileCopyrightText: 2026 Slavi Pantaleev
  2. #
  3. # SPDX-License-Identifier: AGPL-3.0-or-later
  4. ---
  5. name: Molecule
  6. # Unlike the MASH role repositories, where one repository holds one role, every
  7. # role here lives in the same repository. Running every scenario on every push
  8. # would be unaffordable, so a first job works out which roles the push actually
  9. # touched and the matrix is built from that. A push that changes documentation,
  10. # or a role with no scenario yet, runs nothing at all.
  11. on: # yamllint disable-line rule:truthy
  12. push:
  13. paths:
  14. - "roles/custom/**"
  15. - "molecule-shared/**"
  16. - ".github/workflows/molecule.yml"
  17. pull_request:
  18. paths:
  19. - "roles/custom/**"
  20. - "molecule-shared/**"
  21. - ".github/workflows/molecule.yml"
  22. workflow_dispatch:
  23. inputs:
  24. role:
  25. description: "Single role to test (directory name under roles/custom), or empty for all roles that have a scenario"
  26. required: false
  27. type: string
  28. permissions:
  29. contents: read
  30. jobs:
  31. detect:
  32. name: Work out which roles to test
  33. runs-on: ubuntu-latest
  34. # Same rule as the MASH repositories: a pull request from a branch of this
  35. # repository would otherwise run everything twice, once for the push and
  36. # once for the pull request.
  37. if: >-
  38. github.event_name != 'pull_request'
  39. || github.event.pull_request.head.repo.full_name != github.repository
  40. outputs:
  41. roles: ${{ steps.detect.outputs.roles }}
  42. steps:
  43. - name: Check out
  44. uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
  45. with:
  46. fetch-depth: 0
  47. - name: Detect roles with a Molecule scenario that this change touches
  48. id: detect
  49. env:
  50. EVENT_NAME: ${{ github.event_name }}
  51. BASE_SHA: ${{ github.event.pull_request.base.sha }}
  52. BEFORE_SHA: ${{ github.event.before }}
  53. INPUT_ROLE: ${{ inputs.role }}
  54. run: |
  55. set -euo pipefail
  56. have_scenario() {
  57. [ -f "roles/custom/$1/molecule/default/molecule.yml" ]
  58. }
  59. # An explicit request through workflow_dispatch wins over detection.
  60. if [ -n "${INPUT_ROLE}" ]; then
  61. if have_scenario "${INPUT_ROLE}"; then
  62. printf 'roles=["%s"]\n' "${INPUT_ROLE}" >> "$GITHUB_OUTPUT"
  63. else
  64. echo "No scenario at roles/custom/${INPUT_ROLE}/molecule/default" >&2
  65. exit 1
  66. fi
  67. exit 0
  68. fi
  69. # A hand-triggered run with no role named, and any run where the diff
  70. # base is unusable (a new branch, a force push, the very first commit),
  71. # falls back to every role that has a scenario. That is the safe
  72. # direction to fail in: too much testing rather than too little.
  73. base=""
  74. case "${EVENT_NAME}" in
  75. pull_request) base="${BASE_SHA}" ;;
  76. push)
  77. if [ -n "${BEFORE_SHA}" ] && [ "${BEFORE_SHA}" != "0000000000000000000000000000000000000000" ] \
  78. && git cat-file -e "${BEFORE_SHA}^{commit}" 2>/dev/null; then
  79. base="${BEFORE_SHA}"
  80. fi
  81. ;;
  82. esac
  83. # molecule-shared/ is used by every scenario, so a change there means
  84. # every role has to run, not just the ones whose own files moved.
  85. shared_changed=""
  86. if [ -n "${base}" ]; then
  87. shared_changed="$(git diff --name-only "${base}" HEAD -- 'molecule-shared/*' '.github/workflows/molecule.yml' || true)"
  88. fi
  89. if [ -n "${base}" ] && [ -z "${shared_changed}" ]; then
  90. changed="$(git diff --name-only "${base}" HEAD -- 'roles/custom/*' || true)"
  91. candidates="$(printf '%s\n' "${changed}" | awk -F/ 'NF>2 {print $3}' | sort -u)"
  92. echo "Changed roles: ${candidates:-none}"
  93. else
  94. if [ -n "${shared_changed}" ]; then
  95. echo "Shared Molecule files changed; considering every role"
  96. fi
  97. candidates="$(find roles/custom -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort)"
  98. fi
  99. selected=""
  100. for role in ${candidates}; do
  101. if have_scenario "${role}"; then
  102. selected="${selected} ${role}"
  103. fi
  104. done
  105. if [ -z "${selected}" ]; then
  106. echo "Nothing to test"
  107. echo 'roles=[]' >> "$GITHUB_OUTPUT"
  108. exit 0
  109. fi
  110. echo "Testing:${selected}"
  111. json="$(printf '%s\n' ${selected} | jq -R . | jq -c -s .)"
  112. echo "roles=${json}" >> "$GITHUB_OUTPUT"
  113. molecule:
  114. name: "Molecule: ${{ matrix.role }}"
  115. runs-on: ubuntu-latest
  116. needs: detect
  117. if: needs.detect.outputs.roles != '[]'
  118. strategy:
  119. matrix:
  120. role: ${{ fromJson(needs.detect.outputs.roles) }}
  121. fail-fast: false
  122. env:
  123. MOLECULE_DISTRO: ubuntu2604
  124. PY_COLORS: "1"
  125. ANSIBLE_FORCE_COLOR: "1"
  126. steps:
  127. - name: Check out
  128. uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
  129. - name: Set up Python
  130. uses: actions/setup-python@v6
  131. with:
  132. python-version: "3.x"
  133. - name: Install test dependencies
  134. run: python3 -m pip install -r molecule-shared/requirements.txt
  135. - name: Run Molecule
  136. working-directory: roles/custom/${{ matrix.role }}
  137. run: molecule test --scenario-name default