Question: Adding Private GCP Repo Breaks normal pip behaviour When using Google Cloud Platform's Artifact Repository, you have to alter your .pypirc file for any uploads (twine) and your pip.conf for any downloads (pip). For the downloads specifically, you have to add something like: [global] extra-index-url = https://<YOUR-LOCATION>-python.pkg.dev/<YOUR-PROJECT>/<YOUR-REPO-NAME>/simple/  However, by doing this, now anything that will call pip will also check this extra repository, and when doing so, it will ask for a user name and password. This means that anything, like calls behind the scenes that poetry, pdm, pip, or pipx do will all ask for this username and password. Often these requests are being made as part of a non-interactive action, so that everything just stalls. Non-ideal, but working, solution: I ran across this "solution", which does indeed work, but which the author himself says is not the right way to do things because it compromises security, bringing us back to the "infinitely live keys stored on a laptop" days. (I'm sorry, that link is now behind Medium's paywall. In short, the link said that you should use a JSON key and provide that key in your pip.conf and .pypirc files. You can create a JSON key following something like this Google doc showing how to authenticate with a key file.) More secure solution?? But what is the right solution? I want the following:  To be able to run things like pip, pdm, etc. on my local machine and not have them stall, waiting for a username and password that I cannot fill out.  This is both for things that are in fact in my private repository, but also things living in normal PYPI or wherever I look.   To keep the security in place, so that I am being recognized as "ok to do this" because I have authorized myself and my computer via gcloud auth login or something similar (gcloud auth login does nothing to assist with this repo issue, at least not with any flags I tried). And still be able to perform twine actions (upload to registry) without problems. I use newer solutions, specifically pdm, for package build. I need something that uses pyproject.toml, not setup.py, etc. If I perform something like pdm install (or poetry install), I need for credentials to be evaluated without human input. 

Answer: I am still not 100% satisfied with my solution, so the question is still relevant and important, IMHO. However, I have resolved it "good enough", and moved on to other tasks. In a thread above, @insidehustle asked if I could describe how I'm doing it. So even though I don't find this a "solution", I wanted to add it to possibly help him (and others) out with a solution that is good enough. CI/CD We use Google for our cloud provider and GitHub Actions for (most of) our builder. In the GitHub Actions workflow YAML file, I do the following for creating Python packages (I have left my own comments/notes in, because it may help you):  steps: - uses: actions/checkout@v4 - uses: pdm-project/setup-pdm@v4 # With this, set up Python is no longer needed name: setup PDM using python version ${{ inputs.python-version }} with: python-version: ${{ inputs.python-version }} # Range or exact version, same as actions/setup-python update-python: true # Update env with requested python version cache: false # Use cache support. Default path is ./pdm.lock # Authentication does not seem to be providing sufficient rights to PDM, but it # should. We can revisit this. - id: 'auth' name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@v2' with: token_format: 'access_token' workload_identity_provider: ${{ secrets.workload_identity_provider }} service_account: ${{ secrets.service_account }} - name: install '${{ inputs.artifact }}' dependencies env: PYTHON_REPO_USERNAME: ${{ inputs.repo-username }} PYTHON_REPO_PASSWORD: ${{ secrets.python_repo_password }} run: | if [[ ${{ inputs.verbose }} ]] then pdm install --no-default --no-self --verbose else pdm install --no-default --no-self fi - name: run tests on '${{ inputs.artifact }}' (using nox) if: ${{ inputs.run-tests }} env: PYTHON_REPO_USERNAME: ${{ inputs.repo-username }} PYTHON_REPO_PASSWORD: ${{ secrets.python_repo_password }} run: | if [[ ${{ inputs.verbose }} ]] then pdm run nox -f ${{ inputs.noxfile }} --error-on-missing-interpreters --non-interactive --add-timestamp --verbose else pdm run nox -f ${{ inputs.noxfile }} --error-on-missing-interpreters --non-interactive --add-timestamp fi - name: build '${{ inputs.artifact }}' package env: PYTHON_REPO_USERNAME: ${{ inputs.repo-username }} PYTHON_REPO_PASSWORD: ${{ secrets.python_repo_password }} run: | if [[ ${{ inputs.verbose }} ]] then pdm build --verbose else pdm build fi - name: persist package (for later upload to artifact registry) # This is persisting to GH, not to Google Cloud uses: actions/upload-artifact@v4 with: name: ${{ inputs.artifact }} path: ${{ inputs.working-directory }}/dist/ if-no-files-found: ${{ inputs.action-on-upload-fail }}  and then I use Github's Secret Manager to store the things that you see above like secrets.workload_identity_provider. That allows the flexibility of inputs, no secrets being stored in the repo, and an easy way to rotate secrets (I change the actual IAM objects in Google, then update the GHA secrets to reflect the new information).  I then use a similar concept for publishing the Python packages. It's much simpler, because I don't have to worry about "fighting" against my package manager. (Actually, I think that PDM is doing the right thing, it's just that Google and other providers target "broken" old systems and not the newer standards that PDM has adopted.)  There is one more bit of magic to make this work, though: I need to provide my pyproject.toml file with a pointer to my repo, using the secrets mentioned above. To avoid giving away too much company information, I'm editing down the pyproject.toml to just show the core part. [[tool.pdm.source]] name = "insights_python_packages" url = "https://${PYTHON_REPO_USERNAME}:${PYTHON_REPO_PASSWORD}@<our-region>-python.pkg.dev/<our-project>/insights-python-packages/simple/" verify_ssl = true  NOTE: The ${PYTHON_REPO_PASSWORD} is pointing back to the same secret environment variable that is referenced in the GHA YAML file. That is, pdm build works because it has  env: PYTHON_REPO_USERNAME: ${{ inputs.repo-username }} PYTHON_REPO_PASSWORD: ${{ secrets.python_repo_password }}  providing the secrets that are needed to be able to identify the repository. Local Locally, I do the same thing, except that I create a bash script that I source which has the environment variable in it. In other words, I have a file that has the following it in: # GCP Artifact Registry Python repo access (Mgmt Infra) set -x PYTHON_REPO_USERNAME _json_key_base64 set -x PYTHON_REPO_PASSWORD <my_password>  and then I source this file. The downside is that hidden in my local computer (and my colleagues') is the password. I am still not happy with this part of the solution, but the rest is good.  The positive side is that the workflow is exactly the same: I am able to use the same pyproject.toml file, etc. So all I need to do is pdm run nox or pdm build, and everything runs just as it should and does in the CI/CD pipeline.