diff --git a/.github/workflows/CompletePipeline.yml b/.github/workflows/CompletePipeline.yml index 5e896a2a..8ff0dcd1 100644 --- a/.github/workflows/CompletePipeline.yml +++ b/.github/workflows/CompletePipeline.yml @@ -443,6 +443,7 @@ jobs: - Documentation if: >- ${{ !failure() && !cancelled() + && needs.Documentation.result == 'success' && contains(inputs.documentation_steps, 'latex') && contains(inputs.documentation_steps, 'pdf') }} @@ -464,6 +465,9 @@ jobs: - StaticTypeCheck if: >- ${{ !failure() && !cancelled() + && needs.Documentation.result == 'success' + && needs.PublishCoverageResults.result == 'success' + && needs.StaticTypeCheck.result == 'success' && contains(inputs.documentation_steps, 'pages') }} with: @@ -525,6 +529,7 @@ jobs: - ReleasePage if: >- ${{ !failure() && !cancelled() + && needs.Package.result == 'success' && needs.Prepare.outputs.is_release_tag == 'true' }} with: diff --git a/.github/workflows/PrepareJob.yml b/.github/workflows/PrepareJob.yml index 6ea6eecc..cf0c3f7e 100644 --- a/.github/workflows/PrepareJob.yml +++ b/.github/workflows/PrepareJob.yml @@ -418,18 +418,18 @@ jobs: export GH_TOKEN=${{ github.token }} printf "Read second parent of current SHA (%s) ... " "${{ github.ref }}" - FATHER_SHA=$(git rev-parse ${{ github.ref }}^2 2> /dev/null) - if [[ $? -ne 0 || "{FATHER_SHA}" == "" ]]; then + SECOND_PARENT_SHA=$(git rev-parse ${{ github.ref }}^2 2> /dev/null) + if [[ $? -ne 0 || "${SECOND_PARENT_SHA}" == "" ]]; then printf "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}\n" printf "${ANSI_LIGHT_RED}Couldn't read second parent (father) of '%s'.${ANSI_NOCOLOR}\n" "${{ github.ref }}^2" - printf "::error title=GitCommitHistoryError::Couldn't read second parent (father) of '%s'. -> %s\n" "${{ github.ref }}^2" "${FATHER_SHA}" + printf "::error title=GitCommitHistoryError::Couldn't read second parent (father) of '%s'. -> %s\n" "${{ github.ref }}^2" "${SECOND_PARENT_SHA}" exit 1 else printf "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}\n" fi - printf "Search Pull Request to '%s' and branch containing SHA %s ... " "${{ inputs.release_branch }}" "${FATHER_SHA}" - PULL_REQUESTS=$(gh pr list --base "${{ inputs.release_branch }}" --search "${FATHER_SHA}" --state "merged" --json "title,number,headRefOid,mergedBy,mergedAt") + printf "Search Pull Request to '%s' and branch containing SHA %s ... " "${{ inputs.release_branch }}" "${SECOND_PARENT_SHA}" + PULL_REQUESTS=$(gh pr list --base "${{ inputs.release_branch }}" --search "${SECOND_PARENT_SHA}" --state "merged" --json "title,number,headRefOid,mergedBy,mergedAt") if [[ $? -ne 0 ]]; then printf "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}\n" printf "${ANSI_LIGHT_RED}Couldn't search Pull Requests to '%s'. -> %s${ANSI_NOCOLOR}\n" "${{ inputs.release_branch }}" "${PULL_REQUESTS}" @@ -442,19 +442,19 @@ jobs: # an older release Pull Request built from an ancestor. The second parent (father) of a merge commit is the # head commit of the merged branch, so a Pull Request whose 'headRefOid' equals it is the one that created # this merge commit. Newest first, in case a Pull Request was closed and redone from the same branch. - MATCHES=$(printf "%s\n" "${PULL_REQUESTS}" | jq --arg sha "${FATHER_SHA}" '[.[] | select(.headRefOid == $sha)] | sort_by(.mergedAt) | reverse') + MATCHES=$(printf "%s\n" "${PULL_REQUESTS}" | jq --arg sha "${SECOND_PARENT_SHA}" '[.[] | select(.headRefOid == $sha)] | sort_by(.mergedAt) | reverse') MATCH_COUNT=$(printf "%s\n" "${MATCHES}" | jq 'length') - printf "Select Pull Request with head commit %s ... " "${FATHER_SHA}" + printf "Select Pull Request with head commit %s ... " "${SECOND_PARENT_SHA}" if [[ "${MATCH_COUNT}" -eq 0 ]]; then printf "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}\n" - printf "${ANSI_LIGHT_RED}No merged Pull Request to '%s' has head commit '%s'.${ANSI_NOCOLOR}\n" "${{ inputs.release_branch }}" "${FATHER_SHA}" + printf "${ANSI_LIGHT_RED}No merged Pull Request to '%s' has head commit '%s'.${ANSI_NOCOLOR}\n" "${{ inputs.release_branch }}" "${SECOND_PARENT_SHA}" if [[ "$(printf "%s\n" "${PULL_REQUESTS}" | jq 'length')" -eq 0 ]]; then printf "${ANSI_LIGHT_RED}The search returned no candidates at all.${ANSI_NOCOLOR}\n" else printf "${ANSI_LIGHT_RED}Candidates returned by the search: %s${ANSI_NOCOLOR}\n" "$(printf "%s\n" "${PULL_REQUESTS}" | jq --raw-output '[.[] | "#\(.number) (\(.headRefOid[0:7]))"] | join(", ")')" fi - printf "::error title=PullRequest::No merged Pull Request to '%s' has head commit '%s'.\n" "${{ inputs.release_branch }}" "${FATHER_SHA}" + printf "::error title=PullRequest::No merged Pull Request to '%s' has head commit '%s'.\n" "${{ inputs.release_branch }}" "${SECOND_PARENT_SHA}" exit 1 fi printf "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}\n" @@ -462,7 +462,7 @@ jobs: if [[ "${MATCH_COUNT}" -gt 1 ]]; then # Rare, but possible: a Pull Request was closed and recreated from the same branch, so both share a head # commit. The most recently merged one describes this release. - printf "${ANSI_LIGHT_YELLOW}%s Pull Requests share head commit '%s': %s${ANSI_NOCOLOR}\n" "${MATCH_COUNT}" "${FATHER_SHA}" "$(printf "%s\n" "${MATCHES}" | jq --raw-output '[.[] | "#\(.number)"] | join(", ")')" + printf "${ANSI_LIGHT_YELLOW}%s Pull Requests share head commit '%s': %s${ANSI_NOCOLOR}\n" "${MATCH_COUNT}" "${SECOND_PARENT_SHA}" "$(printf "%s\n" "${MATCHES}" | jq --raw-output '[.[] | "#\(.number)"] | join(", ")')" printf "${ANSI_LIGHT_YELLOW}Using the most recently merged one.${ANSI_NOCOLOR}\n" fi diff --git a/.github/workflows/PublishReleaseNotes.yml b/.github/workflows/PublishReleaseNotes.yml index 76c892b6..3eef7ffe 100644 --- a/.github/workflows/PublishReleaseNotes.yml +++ b/.github/workflows/PublishReleaseNotes.yml @@ -689,15 +689,15 @@ jobs: # Search PR with that SHA # Load description of that PR printf "Read second parent of current SHA (%s) ... " "${{ github.ref }}" - FATHER_SHA=$(git rev-parse ${{ github.ref }}^2 2> /dev/null) - if [[ $? -ne 0 || "{FATHER_SHA}" == "" ]]; then + SECOND_PARENT_SHA=$(git rev-parse ${{ github.ref }}^2 2> /dev/null) + if [[ $? -ne 0 || "${SECOND_PARENT_SHA}" == "" ]]; then printf "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}\n" printf "→ ${ANSI_LIGHT_YELLOW}Skipped readout of pull request description. This is not a merge commit.${ANSI_NOCOLOR}\n" else printf "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}\n" - printf "Search pull-request to '%s' and branch containing SHA %s ... " "${{ inputs.release_branch }}" "${FATHER_SHA}" - PULL_REQUESTS=$(gh pr list --base "${{ inputs.release_branch }}" --search "${FATHER_SHA}" --state "merged" --json "title,number,mergedBy,mergedAt,body") + printf "Search pull-request to '%s' and branch containing SHA %s ... " "${{ inputs.release_branch }}" "${SECOND_PARENT_SHA}" + PULL_REQUESTS=$(gh pr list --base "${{ inputs.release_branch }}" --search "${SECOND_PARENT_SHA}" --state "merged" --json "title,number,mergedBy,mergedAt,body") if [[ $? -ne 0 || "${PULL_REQUESTS}" == "" ]]; then printf "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}\n" printf "${ANSI_LIGHT_RED}Couldn't find a merged Pull Request to '%s'. -> %s${ANSI_NOCOLOR}\n" "${{ inputs.release_branch }}" "${PULL_REQUESTS}" diff --git a/doc/Deveopment.rst b/doc/Deveopment.rst index e85c33fc..44db2f42 100644 --- a/doc/Deveopment.rst +++ b/doc/Deveopment.rst @@ -102,6 +102,34 @@ Which function to choose: Do not use ``success() || failure()`` as a substitute for ``!cancelled()``. It is ``false`` if a dependency was *skipped*, because a skipped dependency is neither a success nor a failure. +A status check function tolerates a *skipped* dependency, which is exactly what it is for. A job downloading an +artifact must additionally demand that the job **producing** that artifact succeeded, because a tolerated skip leaves +the artifact missing: + +.. code-block:: yaml + + if: >- + ${{ !failure() && !cancelled() + && needs.Documentation.result == 'success' + && contains(inputs.documentation_steps, 'pages') + }} + +Without the ``needs..result`` term the job starts and fails while downloading: + +.. code-block:: text + + Unable to download artifact(s): Artifact not found for name: documentation-HTML + +.. important:: + + The distinction is between an *unrelated* dependency and a *producing* one. ``AppTesting``, skipped by + ``apptest: 'false'``, has nothing to do with the documentation and must not suppress it - that is the reason the + status check function is there. ``Documentation`` uploads what :ref:`JOBTMPL/PublishToGitHubPages` downloads, so + its skip has to suppress it. + + Observed on a real pipeline: three packaging jobs were cancelled by GitHub, the cascade skipped the documentation + job, and the publishing job ran anyway on the strength of ``!failure() && !cancelled()`` alone. + Conditions combining a status check function with further terms are written as a folded block scalar, one term per line, so a condition can be read - and reviewed - without horizontal scrolling: diff --git a/myFramework/Extension/__init__.py b/myFramework/Extension/__init__.py index aae98269..dd603d0b 100644 --- a/myFramework/Extension/__init__.py +++ b/myFramework/Extension/__init__.py @@ -36,7 +36,7 @@ __email__ = "Paebbels@gmail.com" __copyright__ = "2017-2026, Patrick Lehmann" __license__ = "Apache License, Version 2.0" -__version__ = "7.15.0" +__version__ = "7.15.1" __keywords__ = ["GitHub Actions"] __project_url__ = "https://github.com/pyTooling/Actions" __documentation_url__ = "https://pyTooling.github.io/Actions" diff --git a/myPackage/__init__.py b/myPackage/__init__.py index cfac3c70..9f271b9b 100644 --- a/myPackage/__init__.py +++ b/myPackage/__init__.py @@ -36,7 +36,7 @@ __email__ = "Paebbels@gmail.com" __copyright__ = "2017-2026, Patrick Lehmann" __license__ = "Apache License, Version 2.0" -__version__ = "7.15.0" +__version__ = "7.15.1" __keywords__ = ["GitHub Actions"] __project_url__ = "https://github.com/pyTooling/Actions" __documentation_url__ = "https://pyTooling.github.io/Actions"