diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 4eebe63..ac3481b 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -108,7 +108,46 @@ on: jobs: + check-pr-exists: + runs-on: ubuntu-latest + outputs: + has_pr: ${{ steps.check.outputs.has_pr }} + steps: + - name: Проверка наличия pull request для ветки + id: check + env: + GH_TOKEN: ${{ github.token }} + EVENT_NAME: ${{ github.event_name }} + REF_NAME: ${{ github.ref_name }} + REPOSITORY: ${{ github.repository }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -e + # При push в ветку, для которой уже открыт pull request, контроль + # качества будет выполнен в рамках события pull_request, поэтому + # повторный запуск для события push пропускается во избежание + # дублирования прогонов. + # Проверка работает только если вызывающий workflow выдал токену + # право pull-requests: read; иначе gh завершится с ошибкой и контроль + # качества будет запущен (безопасное поведение по умолчанию). + if [ "$EVENT_NAME" == "push" ] \ + && [ "$REF_NAME" != "$DEFAULT_BRANCH" ] \ + && [ "$REF_NAME" != "main" ] \ + && [ "$REF_NAME" != "master" ] \ + && [ "$REF_NAME" != "develop" ]; then + prs=$(gh pr list --repo "$REPOSITORY" --head "$REF_NAME" --state open --json number --jq 'length' 2>/dev/null || echo "0") + if [ "$prs" -gt 0 ]; then + echo "has_pr=true" >> "$GITHUB_OUTPUT" + else + echo "has_pr=false" >> "$GITHUB_OUTPUT" + fi + else + echo "has_pr=false" >> "$GITHUB_OUTPUT" + fi + test: + needs: [check-pr-exists] + if: needs.check-pr-exists.outputs.has_pr != 'true' runs-on: ${{ inputs.os_version }} env: LANG: ${{ inputs.locale }}.UTF-8 @@ -217,8 +256,8 @@ jobs: sonar: runs-on: ${{ inputs.os_version }} - needs: [test] - if: ${{ (inputs.sonarqube == true) && (github.repository == inputs.github_repository) && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name) }} + needs: [check-pr-exists, test] + if: ${{ (needs.check-pr-exists.outputs.has_pr != 'true') && (inputs.sonarqube == true) && (github.repository == inputs.github_repository) && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name) }} steps: - name: Актуализация uses: actions/checkout@v6.0.2 @@ -267,8 +306,8 @@ jobs: coveralls: runs-on: ${{ inputs.os_version }} - if: inputs.coveralls == true - needs: [test] + if: ${{ (needs.check-pr-exists.outputs.has_pr != 'true') && (inputs.coveralls == true) }} + needs: [check-pr-exists, test] steps: - name: Актуализация uses: actions/checkout@v6.0.2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 11d8d4d..3a7fce4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -89,7 +89,45 @@ on: default: false jobs: + check-pr-exists: + runs-on: ubuntu-latest + outputs: + has_pr: ${{ steps.check.outputs.has_pr }} + steps: + - name: Проверка наличия pull request для ветки + id: check + env: + GH_TOKEN: ${{ github.token }} + EVENT_NAME: ${{ github.event_name }} + REF_NAME: ${{ github.ref_name }} + REPOSITORY: ${{ github.repository }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -e + # При push в ветку, для которой уже открыт pull request, тесты будут + # запущены в рамках события pull_request, поэтому повторный запуск + # для события push пропускается во избежание дублирования прогонов. + # Проверка работает только если вызывающий workflow выдал токену + # право pull-requests: read; иначе gh завершится с ошибкой и тесты + # будут запущены (безопасное поведение по умолчанию). + if [ "$EVENT_NAME" == "push" ] \ + && [ "$REF_NAME" != "$DEFAULT_BRANCH" ] \ + && [ "$REF_NAME" != "main" ] \ + && [ "$REF_NAME" != "master" ] \ + && [ "$REF_NAME" != "develop" ]; then + prs=$(gh pr list --repo "$REPOSITORY" --head "$REF_NAME" --state open --json number --jq 'length' 2>/dev/null || echo "0") + if [ "$prs" -gt 0 ]; then + echo "has_pr=true" >> "$GITHUB_OUTPUT" + else + echo "has_pr=false" >> "$GITHUB_OUTPUT" + fi + else + echo "has_pr=false" >> "$GITHUB_OUTPUT" + fi + build: + needs: [check-pr-exists] + if: needs.check-pr-exists.outputs.has_pr != 'true' runs-on: ${{ matrix.os }} env: LANG: ${{ inputs.locale }}.UTF-8 diff --git a/README.md b/README.md index 0c0a2f4..2e88a33 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ lib.system=../oscript_modules Сборочная линия для выполнения тестирования библиотеки. Позволяет запустить матричную сборку на настраиваемом списке операционных систем (по умолчанию Windows, Ubuntu и macOS) на нескольких версиях движка OneScript. Поддерживается запуск из ветки, из pull request и ручной запуск из информации о конкретном workflow. +> [!NOTE] +> Чтобы избежать двойного прогона, при событии `push` в ветку, для которой уже открыт pull request, тестирование пропускается — оно будет выполнено в рамках события `pull_request`. Для ветки по умолчанию (а также `main`, `master` и `develop`) тестирование выполняется всегда. +> Для работы этой проверки вызывающему workflow необходимо выдать токену право `pull-requests: read` (см. блок `permissions` в примерах ниже). Если право не выдано, тестирование запускается как обычно — и на `push`, и на `pull_request`. + Файл workflow: [https://github.com/autumn-library/workflows/blob/main/.github/workflows/test.yml](https://github.com/autumn-library/workflows/blob/main/.github/workflows/test.yml) Общие параметры: @@ -74,6 +78,10 @@ on: pull_request: workflow_dispatch: +permissions: + contents: read + pull-requests: read # для пропуска повторного прогона на push при открытом PR + jobs: test: uses: autumn-library/workflows/.github/workflows/test.yml@v1 @@ -208,6 +216,10 @@ jobs: Поддерживается запуск из ветки, из pull request и ручной запуск из информации о конкретном workflow. > Анализ pull request из форков для задачи SonarQube пока не поддерживается. +> [!NOTE] +> Чтобы избежать двойного прогона, при событии `push` в ветку, для которой уже открыт pull request, контроль качества пропускается — он будет выполнен в рамках события `pull_request`. Для ветки по умолчанию (а также `main`, `master` и `develop`) контроль качества выполняется всегда. +> Для работы этой проверки вызывающему workflow необходимо выдать токену право `pull-requests: read` (см. блок `permissions` в примерах ниже). Если право не выдано, контроль качества запускается как обычно — и на `push`, и на `pull_request`. + Файл workflow: [https://github.com/autumn-library/workflows/blob/main/.github/workflows/sonar.yml](https://github.com/autumn-library/workflows/blob/main/.github/workflows/sonar.yml) Параметры: @@ -267,6 +279,10 @@ on: pull_request: workflow_dispatch: +permissions: + contents: read + pull-requests: read # для пропуска повторного прогона на push при открытом PR + jobs: sonar: uses: autumn-library/workflows/.github/workflows/sonar.yml@v1