diff --git a/.github/workflows/crowdin-validator.yml b/.github/workflows/crowdin-validator.yml new file mode 100644 index 0000000..75c861b --- /dev/null +++ b/.github/workflows/crowdin-validator.yml @@ -0,0 +1,109 @@ +name: Crowdin validator (Bitrise) + +# Bridges GitHub PR events to the Bitrise `crowdin_validator` workflow. +# +# Bitrise's own GitHub webhook auto-registration is blocked for this app +# (`register_webhook` -> provider_reauth_required: "GitHub identity is not +# available for user") until someone reauthorizes Bitrise's GitHub connection +# in Bitrise account settings. Until then, this workflow is the "hook": it +# triggers the real validation logic on Bitrise (scripts/crowdin_validator.py) +# and fails this GitHub check if that build fails -- which is what branch +# protection actually needs to block a merge, regardless of whether Bitrise's +# own webhook is wired up. +# +# Requires one repo secret: BITRISE_API_TOKEN (a Bitrise personal access +# token, or workspace API token, with at least Developer access to the +# "loop-localization" app -- Bitrise -> Account Settings -> Security -> +# Personal access tokens). Not the Build trigger token; polling build status +# needs a real API token per Bitrise's docs. +# +# The trigger payload intentionally omits pull_request_* fields: Bitrise +# tries to resolve those against GitHub too, which hits the same broken +# identity and makes the *trigger* call itself fail with the same +# "GitHub identity is not available for user" error. Triggering a plain +# branch build (branch + commit_hash) sidesteps that entirely -- the +# validator script only needs `git fetch origin main` + a diff, not a PR +# merge ref. + +on: + pull_request: + branches: [main] + +concurrency: + group: crowdin-validator-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + crowdin_validator: + runs-on: ubuntu-latest + env: + BITRISE_APP_SLUG: acab23b7-43de-4110-8288-01fbc83fd63d + steps: + - name: Trigger Bitrise crowdin_validator build + id: trigger + env: + BITRISE_API_TOKEN: ${{ secrets.BITRISE_API_TOKEN }} + run: | + set -euo pipefail + if [ -z "${BITRISE_API_TOKEN:-}" ]; then + echo "::error::Repo secret BITRISE_API_TOKEN is not set -- see comments in this workflow file." + exit 1 + fi + + payload=$(jq -n \ + --arg workflow_id "crowdin_validator" \ + --arg branch "${{ github.head_ref }}" \ + --arg commit_hash "${{ github.event.pull_request.head.sha }}" \ + --arg commit_message "${{ github.event.pull_request.title }}" \ + '{ + hook_info: {type: "bitrise"}, + build_params: { + workflow_id: $workflow_id, + branch: $branch, + commit_hash: $commit_hash, + commit_message: $commit_message, + skip_git_status_report: true + } + }') + + response=$(curl -sS -w '\n%{http_code}' -X POST \ + "https://api.bitrise.io/v0.1/apps/${BITRISE_APP_SLUG}/builds" \ + -H "Authorization: ${BITRISE_API_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$payload") + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | sed '$d') + echo "$body" + + if [ "$http_code" -ge 300 ]; then + echo "::error::Failed to trigger Bitrise build (HTTP $http_code)" + exit 1 + fi + + build_slug=$(echo "$body" | jq -er '.build_slug // .results[0].build_slug // empty') + build_url=$(echo "$body" | jq -er '.build_url // .results[0].build_url // empty') + echo "build_slug=$build_slug" >> "$GITHUB_OUTPUT" + echo "Triggered: $build_url" + echo "### Bitrise build: [$build_slug]($build_url)" >> "$GITHUB_STEP_SUMMARY" + + - name: Wait for Bitrise build result + env: + BITRISE_API_TOKEN: ${{ secrets.BITRISE_API_TOKEN }} + BUILD_SLUG: ${{ steps.trigger.outputs.build_slug }} + run: | + set -euo pipefail + # status: 0 = in-progress, 1 = success, 2 = failed, 3 = aborted + for _ in $(seq 1 90); do + resp=$(curl -sS "https://api.bitrise.io/v0.1/apps/${BITRISE_APP_SLUG}/builds/${BUILD_SLUG}" \ + -H "Authorization: ${BITRISE_API_TOKEN}") + status=$(echo "$resp" | jq -r '.data.status') + status_text=$(echo "$resp" | jq -r '.data.status_text') + echo "Bitrise build status: $status ($status_text)" + case "$status" in + 1) echo "Bitrise crowdin_validator build succeeded."; exit 0 ;; + 2|3) echo "::error::Bitrise crowdin_validator build finished with status_text=$status_text"; exit 1 ;; + esac + sleep 10 + done + echo "::error::Timed out waiting for the Bitrise build to finish" + exit 1