I am trying to use the Azure pipeline to publish a Python package to Artifact’s feed.
I could do it from my local machine and upload the package using Twine, but I have an authentication issue in the pipeline.
trigger:
- main
pool:
vmImage: ubuntu-22.04
variables:
pip_cache_dir: '$(Pipeline.Workspace)/.pip_cache'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.10'
addToPath: true
- bash: |
python -m venv worker_venv
source worker_venv/bin/activate
pip install --upgrade pip
pip install pipenv
pipenv requirements > requirements.txt
pipenv requirements --dev > requirements-dev.txt
pip install --cache-dir $(pip_cache_dir) -r ./requirements.txt
pip install --target="./.python_packages/lib/site-packages" --cache-dir $(pip_cache_dir) -r ./requirements.txt
displayName: 'Install tools'
- script: |
source worker_venv/bin/activate
python setup.py sdist bdist_wheel
displayName: 'Build package'
- task: TwineAuthenticate@1
inputs:
artifactFeed: sample-feed-01
- script: |
source worker_venv/bin/activate
python -m twine upload --verbose --config-file $(PYPIRC_PATH) --repository-url https://pkgs.dev.azure.com/**company**/Platform/_packaging/sample-feed-01/pypi/upload/ dist/*
env:
TWINE_USERNAME: "azure"
TWINE_PASSWORD: $(PYPI_TOKEN)
displayName: 'Upload package to Azure Artifacts'
I tried everything, including GPT-4, but the solutions seem wrong or outdated.
this is the error:
/usr/bin/bash --noprofile --norc /home/vsts/work/_temp/75d0c60b-0c2a-44e9-be0f-29d838a3b86e.sh
Uploading distributions to
https://pkgs.dev.azure.com/**company**/Platform/_packaging/sample-feed-01/pypi/up
load/
INFO dist/**package**.whl (2.6 KB)
INFO dist/**package**.tar.gz (2.6 KB)
INFO username set by command options
INFO password set by command options
INFO username: azure
INFO password: <hidden>
Uploading **package**.whl
25l
0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/5.7 kB • --:-- • ?
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.7/5.7 kB • 00:00 • ?
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.7/5.7 kB • 00:00 • ?
25hINFO Response from
https://pkgs.dev.azure.com/**company**/Platform/_packaging/sample-feed-0
1/pypi/upload/:
401 Unauthorized
INFO {"$id":"1","innerException":null,"message":"TF400813: The user
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' is not authorized to access this
resource.","typeName":"Microsoft.TeamFoundation.Framework.Server.Unauth
orizedRequestException,
Microsoft.TeamFoundation.Framework.Server","typeKey":"UnauthorizedReque
stException","errorCode":0,"eventId":3000}
ERROR HTTPError: 401 Unauthorized from
https://pkgs.dev.azure.com/**company**/Platform/_packaging/sample-feed-0
1/pypi/upload/
Unauthorized
I have some doubts about 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
as user name, which I did not obfuscate, and that is what I see in the pipeline.
any help would be appreciated
2
Answers
You can use the
publishArtifact
job from Azure: https://learn.microsoft.com/nl-nl/azure/devops/pipelines/tasks/reference/publish-build-artifacts-v1?view=azure-pipelines.We do this with Poetry. Therefore you need Azure’s
TwineAuthenticate
step: https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/twine-authenticate-v1?view=azure-pipelines. It will look something like this:Go the Azure Artifacts feed you want to publish the Python package to, then navigate to Feed Settings > Permissions page to check and ensure the following identities have been assigned with
Contributor
role at least.Project Collection Build Service ({OrgName})
{ProjectName} Build Service ({OrgName})
For more details, see "Job access tokens".
After configuring the permission role, in the pipeline, you can build and publish the Python package like as below.
With this way, you do not need to provide your PAT/password to authenticate.
For more details, see "Publish Python packages with Azure Pipelines".
EDIT:
By default, the pipeline will use one of the following build identities (also as mentioned above) to access the Azure Artifacts feeds and other resources within current organization:
Project Collection Build Service ({OrgName})
: Can access resources with full/partial permissions across projects within current organization by default.{ProjectName} Build Service ({OrgName})
: Can access resources with full/partial permissions only within the current project by default.On the Organization Settings (and Project Settings), there are two options:
Limit job authorization scope to current project for non-release pipelines
Limit job authorization scope to current project for release pipelines
If the options are enabled, the pipelines use the identity "
{ProjectName} Build Service ({OrgName})
". If the options are disabled, the identity "Project Collection Build Service ({OrgName})
" is used.The
TwineAuthenticate@1
task will use one of above build identities to generate the twine credentials and set the credentials to the environment variablePYPIRC_PATH
.Since the identities might not have the full access to the feed by default, to assign the required permission role to the identities, you need to click the "
Add users/groups
" button, then on the pop-up window, search for and add the identities with the required roles.