2026-05-11 Mon
Cross-Repo Authentication and Python Package Management with GitHub/Apps
Use Case
- In the context of a GitHub/Enterprise, we had two use cases.
Initial Use Case / Need
- In a GitHub/Action in
my-org/repo-a, call uv/sync on a python project that has a dependency on a python package frommy-org/repo-bexpressed as a git installation path
- In a GitHub/Action in
Long-Term Use Case / Need
- In any GitHub Action in
my-org, call uv/sync on a python project that has a dependency on a python package from any other GitHub/Repo marked asInternal
- In any GitHub Action in
Challenge
GITHUB_TOKENdoes not by default have the ability to respect repositories that are marked asInternalto a GitHub/Enterprise. See GITHUB_TOKEN does not have permissions to read other private repos in the same organization · community · Discussion #46566 for more discussion.
Options
A - Use a GitHub App - CHOSEN
- Create a github app with the
Contents: readpermission onmy-org/repo-b - Use GitHub/Action/Create GitHub App Token action to obtain a short-lived credential
- Use the short-lived credential to do the uv/sync after
- Create a github app with the
B - Use a Service User
- Create a github service user and grant it access to the GitHub/Org
- Create a GitHub Fine-Grained Access Token with the
Contents: readpermission onmy-org/repo-b
Implementing Option A - Use a GitHub/App
- Created a GitHub/App titled
<org>-ci-read-repo-contents-app - The app had repo
contents: readpermissions - Encountered some difficulty finding how a GitHub/Org/Admin could create a GitHub/App "inside" or owned by the GitHub Org. Ended up creating it in a personal account and transferring its ownership to the org.
- After the app was owned by the GitHub/Enterprise GitHub/Org, GitHub/App/Settings were configured to enable reading all repositories.
- Ensured that GitHub/App/Client ID and GitHub/App/Private Key as GitHub/Org/Secrets.
- In
my-org/my-repo-a, updatepyproject.toml: - In
my-org/my-repo-a, used the following GitHub/Action to pull the secrets out, generate a GitHub/App/Token. Everything here is scoped tomy-org/MY_ORG- yml
- name: Generate GitHub App token id: app-token uses: actions/create-github-app-token@v1 with: app-id: ${{ secrets.MY_ORG_CI_READ_REPO_CONTENTS_APP_CLIENT_ID }} private-key: ${{ secrets.MY_ORG_CI_READ_REPO_CONTENTS_APP_PRIVATE_KEY }} owner: my-org - name: Configure git authentication for private repos run: | git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "https://github.com/" - name: Install uv uses: astral-sh/setup-uv@v8.1.0 with: version: "latest" - name: Set up Python run: uv python install 3.12 - name: Install dependencies run: uv sync
- This ended up working.
- In practice, in order to get to this point, first created
.github/workflows/test-github-app-access.ymlwith just the steps necessary to prove cross-repo access.
- Created a GitHub/App titled