From 612cd01743ec5ff86286e1806d5b86a9265cd2ec Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 5 Sep 2025 18:26:08 +0200 Subject: [PATCH] maint(linux): allow to skip API check This change adds an option to skip the API checks during a build. This can be done by adding the trailer `Keyman-Api-Check: skip` to the PR description. Fixes: #10454 Test-bot: skip Keyman-Api-Check: skip --- .github/workflows/api-verification.yml | 10 +++++-- .github/workflows/deb-packaging.yml | 2 ++ docs/core-api-verification.md | 11 ++++++++ resources/build/ci/trigger-build-bot.inc.sh | 28 +++++++++++++++++++ resources/build/ci/trigger-builds.inc.sh | 5 +++- .../test/build-bot/trigger-build-bot.test.sh | 14 ++++++++++ .../teamcity/triggers/trigger-test-builds.sh | 5 +++- 7 files changed, 70 insertions(+), 5 deletions(-) diff --git a/.github/workflows/api-verification.yml b/.github/workflows/api-verification.yml index e8cc9aa95a..af6bc682dc 100644 --- a/.github/workflows/api-verification.yml +++ b/.github/workflows/api-verification.yml @@ -23,6 +23,7 @@ jobs: GIT_BRANCH: ${{ steps.environment_step.outputs.GIT_BRANCH }} GIT_BASE_BRANCH: ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }} GIT_USER: ${{ steps.environment_step.outputs.GIT_USER }} + SKIP_API_CHECK: ${{ steps.environment_step.outputs.SKIP_API_CHECK }} steps: - name: Restore artifacts @@ -40,7 +41,7 @@ jobs: - name: Set pending status on PR builds id: set_status - if: steps.environment_step.outputs.IS_TEST_BUILD == 'true' + if: steps.environment_step.outputs.IS_TEST_BUILD == 'true' && steps.environment_step.outputs.SKIP_API_CHECK != 'true' shell: bash run: | gh api \ @@ -53,6 +54,7 @@ jobs: -f context="$STATUS_CONTEXT" - name: Checkout + if: steps.environment_step.outputs.SKIP_API_CHECK != 'true' uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 with: ref: '${{ steps.environment_step.outputs.GIT_SHA }}' @@ -61,11 +63,13 @@ jobs: path: ${{ github.workspace }}/keyman/ - name: Install devscripts + if: steps.environment_step.outputs.SKIP_API_CHECK != 'true' uses: ./keyman/.github/actions/apt-install with: packages: devscripts equivs - name: "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }})" + if: steps.environment_step.outputs.SKIP_API_CHECK != 'true' run: | echo "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }}):" >> $GITHUB_STEP_SUMMARY @@ -79,17 +83,17 @@ jobs: verify 2>> $GITHUB_STEP_SUMMARY - name: Archive .symbols file + if: steps.environment_step.outputs.SKIP_API_CHECK != 'true' && always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: libkeymancore.symbols path: ${{ github.workspace }}/keyman/linux/debian/tmp/DEBIAN/symbols - if: always() set_status: name: Set result status on PR builds needs: [api_verification] runs-on: ubuntu-latest - if: ${{ always() && needs.api_verification.outputs.IS_TEST_BUILD == 'true' }} + if: ${{ always() && needs.api_verification.outputs.IS_TEST_BUILD == 'true' && needs.api_verification.outputs.SKIP_API_CHECK != 'true' }} steps: - name: Set success if: needs.api_verification.result == 'success' diff --git a/.github/workflows/deb-packaging.yml b/.github/workflows/deb-packaging.yml index a40fcb7259..472adf91b0 100644 --- a/.github/workflows/deb-packaging.yml +++ b/.github/workflows/deb-packaging.yml @@ -23,6 +23,7 @@ on: # baseRef: The ref of the previous commit. For a PR the same as `baseBranch`. # user: The user that triggered the build or created the PR # isTestBuild: false for Releases, otherwise true +# skipApiCheck: true to skip the API check, otherwise false env: COLOR_GREEN: "\e[32m" @@ -332,6 +333,7 @@ jobs: echo "GIT_BRANCH=${{ github.event.client_payload.branch }}" >> artifacts/env echo "GIT_BASE_BRANCH=${{ github.event.client_payload.baseBranch }}" >> artifacts/env echo "GIT_USER=${{ github.event.client_payload.user }}" >> artifacts/env + echo "SKIP_API_CHECK=${{ github.event.client_payload.skipApiCheck }}" >> artifacts/env - name: Cache artifacts uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 diff --git a/docs/core-api-verification.md b/docs/core-api-verification.md index fc3e0f629d..0bf266676f 100644 --- a/docs/core-api-verification.md +++ b/docs/core-api-verification.md @@ -99,6 +99,17 @@ the API version number in `CORE_API_VERSION.md`. If the API version numbers in `CORE_API_VERSION.md` and in `libkeymancore.symbols` don't match the API verification will fail. +## Skipping the API check + +Sometimes we have a PR that intentionally does not change the API version +number. To skip the API checks in this case, the trailer + +```text +Keyman-Api-Check: skip +``` + +can be added to the PR description. + ## How this works `.github/workflows/api-verification.yml` contains a `Verify API` step diff --git a/resources/build/ci/trigger-build-bot.inc.sh b/resources/build/ci/trigger-build-bot.inc.sh index f7cdc815f8..fb6ed4c34c 100644 --- a/resources/build/ci/trigger-build-bot.inc.sh +++ b/resources/build/ci/trigger-build-bot.inc.sh @@ -39,6 +39,34 @@ function test_bot_check_pr_body() { fi } +# +# Check the Keyman-Api-Check command whether or not to run API checks. +# Any value other than 'ignore' or no Keyman-Api-Check command will run +# the API checks. +# +# Parameters: +# 1: PR number (not currently used) +# 2: PR JSON data from api.github.com/repos/keymanapp/keyman/pulls/# +# +function is_skip_keyman_api_check() { + local PRNUM=$1 + local prinfo="$2" + local prbody prApiCheck + + set -o noglob + IFS=$'\n' + prbody="$(echo "${prinfo}" | "${JQ}" -r '.body')" + prApiCheck="$(echo "${prbody}" | grep 'Keyman-Api-Check:' | cut -d: -f 2 - | tr -d '[:space:]')" + unset IFS + set +o noglob + + if [[ "${prApiCheck}" == "skip" ]]; then + echo "true" + else + echo "false" + fi +} + # # Check PR commit messages for Build-bot commands. Later commands override # earlier ones. Also checks PR body for any overriding commands. Note, only diff --git a/resources/build/ci/trigger-builds.inc.sh b/resources/build/ci/trigger-builds.inc.sh index c5df3d30a9..d1110a19a1 100644 --- a/resources/build/ci/trigger-builds.inc.sh +++ b/resources/build/ci/trigger-builds.inc.sh @@ -84,12 +84,14 @@ function triggerTeamCityBuild() { # 2: 'skip' - don't run build; 'build' - run build and unit tests; 'test' - run build, unit tests, and deploy # 3: Action name # 4: branch name in git +# 5: 'true' to skip API checks, 'false' to run them (optional, default 'false') # function triggerGitHubActionsBuild() { local IS_TEST_BUILD="$1" local BUILD_LEVEL="$2" local GITHUB_ACTION="$3" local GIT_BRANCH="$4" + local SKIP_API_CHECK="${5:-"false"}" local GIT_BASE_BRANCH="${GIT_BRANCH}" local GIT_USER="keyman-server" local GIT_BUILD_SHA GIT_BASE_REF JSON @@ -127,7 +129,8 @@ function triggerGitHubActionsBuild() { \"baseRef\": \"${GIT_BASE_REF}\", \ \"user\": \"${GIT_USER}\", \ \"isTestBuild\": \"${IS_TEST_BUILD}\", \ - \"buildLevel\": \"${BUILD_LEVEL}\" \ + \"buildLevel\": \"${BUILD_LEVEL}\", \ + \"skipApiCheck\": \"${SKIP_API_CHECK}\" \ }}" echo "GitHub Action Data: ${DATA}" diff --git a/resources/build/test/build-bot/trigger-build-bot.test.sh b/resources/build/test/build-bot/trigger-build-bot.test.sh index a39b8361ae..ce37c718a9 100755 --- a/resources/build/test/build-bot/trigger-build-bot.test.sh +++ b/resources/build/test/build-bot/trigger-build-bot.test.sh @@ -216,7 +216,21 @@ _do_test_test_bot_check_pr_body() { #---------------------------------------------------------------------------------------------------- +test_is_skip_keyman_api_check() { + builder_echo start test_is_skip_keyman_api_check 'START TEST: test_is_skip_keyman_api_check' + result=$(is_skip_keyman_api_check 1 '{ "body": "Keyman-Api-Check: skip" }') + assert-equal "${result}" "true" "PR #1: 'Keyman-Api-Check: skip' should return true" + result=$(is_skip_keyman_api_check 2 '{ "body": "PR message" }') + assert-equal "${result}" "false" "PR #2: omitted 'Keyman-Api-Check' should return false" + result=$(is_skip_keyman_api_check 3 '{ "body": "Keyman-Api-Check: invalid" }') + assert-equal "${result}" "false" "PR #3: invalid data for 'Keyman-Api-Check' should return false" + builder_echo end test_is_skip_keyman_api_check success 'SUCCESS: test_is_skip_keyman_api_check' +} + +#---------------------------------------------------------------------------------------------------- + test_build_bot_verify_platforms test_build_bot_update_commands test_build_bot_check_messages test_test_bot_check_pr_body +test_is_skip_keyman_api_check diff --git a/resources/teamcity/triggers/trigger-test-builds.sh b/resources/teamcity/triggers/trigger-test-builds.sh index ce1af8e3ee..52a9ffc1da 100755 --- a/resources/teamcity/triggers/trigger-test-builds.sh +++ b/resources/teamcity/triggers/trigger-test-builds.sh @@ -85,7 +85,7 @@ function triggerTestBuilds() { builder_echo "DRY RUN: Triggering GitHub action build ${job}/${branch}, level = ${platformBuildLevel}" else builder_echo "Triggering GitHub action build ${job}/${branch}, level = ${platformBuildLevel}" - triggerGitHubActionsBuild true "${platformBuildLevel}" "${job}" "${branch}" + triggerGitHubActionsBuild true "${platformBuildLevel}" "${job}" "${branch}" "${KEYMAN_API_CHECK_SKIP}" fi else if builder_has_option --dry-run; then @@ -240,6 +240,8 @@ find_platform_changes # This will modify the build_platforms array # +KEYMAN_API_CHECK_SKIP="false" + if [[ "${prremote}" == "origin" ]]; then # We only accept Build-bot commands on trusted local origin PRs cd "${KEYMAN_ROOT}/resources/build/ci/github" @@ -254,6 +256,7 @@ if [[ "${prremote}" == "origin" ]]; then prcommits=$(${NODE_WRAPPER} api-pull-commits.mjs "${GITHUB_TOKEN}" "${PRNUM}") test_bot_check_pr_body "${PRNUM}" "${prinfo}" build_bot_check_messages "${PRNUM}" "${prinfo}" "${prcommits}" + KEYMAN_API_CHECK_SKIP="$(is_skip_keyman_api_check "${PRNUM}" "${prinfo}")" fi #