mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 16:02:14 +00:00
141ed7bae0
check-write-access is additive by design: every caller ORs its `authorized` output with `github.event.comment.author_association`, so a failure should degrade to the author_association path, not block anything. It does not. `claude`, `codex` and `pi` all `needs: [parse, check-access, plan]`, so a failed check-access skips `plan` and with it all three reviewers. Any disruption to the app credentials — an unset `INTERNAL_APP_ID`, a rotated `INTERNAL_APP_KEY`, the app uninstalled from the org — turns a redundant authorization probe into a total /review outage. Guard the token minting and fall back to the default token, which still resolves public members and repo collaborators; private members fall through to author_association exactly as they did before this workflow existed. Found while porting these workflows to windmill-helm-charts (windmill-labs/windmill-helm-charts#656), where the app credentials are not guaranteed to be present. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
75 lines
3.1 KiB
YAML
75 lines
3.1 KiB
YAML
name: Check Write Access
|
|
|
|
# Authorizes a user to trigger privileged command workflows (/review, /ai, /plan,
|
|
# /updatesqlx, ...). The webhook author_association reports PRIVATE org members as
|
|
# CONTRIBUTOR/NONE (only public members show as MEMBER), so command jobs can't gate on
|
|
# it alone. This mints the internal GitHub App token — which can see private members —
|
|
# and confirms the user is a member or has write access to the repo. The app token is
|
|
# minted fresh per run, so unlike the old ORG_ACCESS_TOKEN PAT it never expires.
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
username:
|
|
required: true
|
|
type: string
|
|
description: 'The user whose access to verify'
|
|
trusted_bot:
|
|
required: false
|
|
type: string
|
|
default: 'windmill-internal-app[bot]'
|
|
description: 'A bot login that is always authorized'
|
|
outputs:
|
|
authorized:
|
|
description: 'true if the user is the trusted bot, an org member, or has repo write access'
|
|
value: ${{ jobs.check.outputs.authorized }}
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
authorized: ${{ steps.check.outputs.authorized }}
|
|
steps:
|
|
# This check is purely additive: callers OR it with author_association, so it must
|
|
# never fail the job. Failing here would block every dependent reviewer job through
|
|
# `needs`, turning an unconfigured or misconfigured app into a total review outage
|
|
# rather than a fallback to the author_association path.
|
|
- name: Mint internal app token
|
|
id: app
|
|
if: vars.INTERNAL_APP_ID != ''
|
|
continue-on-error: true
|
|
uses: actions/create-github-app-token@v2
|
|
with:
|
|
app-id: ${{ vars.INTERNAL_APP_ID }}
|
|
private-key: ${{ secrets.INTERNAL_APP_KEY }}
|
|
owner: ${{ github.repository_owner }}
|
|
|
|
- name: Resolve authorization
|
|
id: check
|
|
env:
|
|
# Without the app token, the default token still resolves public members and
|
|
# repo collaborators; private members simply fall through to author_association.
|
|
GH_TOKEN: ${{ steps.app.outputs.token || github.token }}
|
|
USERNAME: ${{ inputs.username }}
|
|
TRUSTED_BOT: ${{ inputs.trusted_bot }}
|
|
REPO: ${{ github.repository }}
|
|
run: |
|
|
if [ "$USERNAME" = "$TRUSTED_BOT" ]; then
|
|
echo "authorized=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
ORG="${REPO%%/*}"
|
|
# Org membership resolves private members too (204 = member, 404 = not).
|
|
if gh api "orgs/$ORG/members/$USERNAME" --silent 2>/dev/null; then
|
|
echo "authorized=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
# Fallback: effective repo permission (also covers outside collaborators).
|
|
PERM=$(gh api "repos/$REPO/collaborators/$USERNAME/permission" --jq '.permission' 2>/dev/null || echo none)
|
|
if [ "$PERM" = "admin" ] || [ "$PERM" = "write" ]; then
|
|
echo "authorized=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "authorized=false" >> "$GITHUB_OUTPUT"
|
|
echo "$USERNAME is neither the trusted bot, an org member, nor a repo writer."
|
|
fi
|