Poetry 无法通过 Trusted Publishing 将包发布到 Jfrog 的 PyPi 工件

问题描述 投票:0回答:1

我在通过 Trusted Publishing 将软件包发布到 Jfrog 的 PyPi 工件时遇到问题。我已经尝试了多种方法,但所有结果都是相同的 401 错误

Wrong username was used
。不知道这意味着什么,因为我没有使用任何用户名来向 Jfrog 进行身份验证。我在这里缺少一些东西。我检查过,从 Jfrog 获取访问令牌的过程有效 - GitHub OIDC 提供商能够从 Jfrog 获取访问令牌。在我看来,访问令牌在某种程度上被错误地解释并被诗歌用来与 Jfrog 进行身份验证。

  packages_publish:
    needs:
      - generate_packages
      - packages_test
    runs-on: ubuntu-20.04
    container: <PYTHONRUNTIME_IMAGE>
    env:
      OIDC_AUDIENCE: 'jfrog-github'
      OIDC_ITEGRATION_NAME: 'github-oidc-integration'
    #if: github.ref == 'refs/heads/main'
    permissions: write-all
    steps:
      - name: Install dependencies for authorization
        run: apt update && apt install -y jq
      - name: Get ID Token
        id: idtoken
        run: |
          ID_TOKEN=$(curl -sLS -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
          "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=$OIDC_AUDIENCE" | jq .value | tr -d '"')
          echo "ID_TOKEN=${ID_TOKEN}" >> $GITHUB_OUTPUT
      - name: Fetch Access Token from Artifactory
        id: fetch_access_token
        env:
          ID_TOKEN: ${{ steps.idtoken.outputs.id_token }}
        run: |
          ACCESS_TOKEN=$(curl \
          -X POST \
          -H "Content-type: application/json" \
          https://example.jfrog.io/access/api/v1/oidc/token \
          -d \
          "{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"$ID_TOKEN\", \"provider_name\": \"$OIDC_ITEGRATION_NAME\"}" | jq .access_token | tr -d '"')
          echo ACCESS_TOKEN=$ACCESS_TOKEN >> $GITHUB_OUTPUT
      - uses: actions/checkout@v3
      - name: Publish to artifactory
        env:
          POETRY_PYPI_TOKEN_EXAMPLE: ${{ steps.fetch_access_token.outputs.access_token }}
          POETRY_REPOSITORIES_EXAMPLE_URL: 'https://example.jfrog.io/artifactory/api/pypi/pypi-general-local'
          ACCESS_TOKEN: '${{ steps.fetch_access_token.outputs.access_token }}'
        run: |
          cd packages/<package-example>
          sed -i "0,/\(version = \"[0-9]\+.[0-9]\+\)\"/s//\1.${{ github.run_number }}\"/" pyproject.toml
          poetry config pypi-token.example $POETRY_PYPI_TOKEN_EXAMPLE
          poetry publish --build -r example -vvv

完整错误发布输出:

Publishing package-example (0.1.50) to example
 - Uploading package-example-0.1.50-py3-none-any.whl 0%
 - Uploading package-example-0.1.50-py3-none-any.whl 100%
  Stack trace:
  1  /opt/poetry/venv/lib/python3.10/site-packages/poetry/publishing/uploader.py:265 in _upload_file
      263│                     bar.display()
      264│                 else:
    → 265│                     resp.raise_for_status()
      266│             except (requests.ConnectionError, requests.HTTPError) as e:
      267│                 if self._io.output.is_decorated():
  HTTPError
  401 Client Error:  for url: https://example.jfrog.io/artifactory/api/pypi/pypi-general-local
  at /opt/poetry/venv/lib/python3.10/site-packages/requests/models.py:1021 in raise_for_status
      1017│                 f"{self.status_code} Server Error: {reason} for url: {self.url}"
      1018│             )
      1019│ 
      1020│         if http_error_msg:
    → 1021│             raise HTTPError(http_error_msg, response=self)
      1022│ 
      1023│     def close(self):
      1024│         """Releases the connection back to the pool. Once this method has been
      1025│         called the underlying ``raw`` object must not be accessed again.
The following error occurred when trying to handle this error:
  Stack trace:
  11  /opt/poetry/venv/lib/python3.10/site-packages/cleo/application.py:327 in run
       325│ 
       326│             try:
     → 327│                 exit_code = self._run(io)
       328│             except BrokenPipeError:
       329│                 # If we are piped to another process, it may close early and send a
  10  /opt/poetry/venv/lib/python3.10/site-packages/poetry/console/application.py:190 in _run
       188│         self._load_plugins(io)
       189│ 
     → 190│         exit_code: int = super()._run(io)
       191│         return exit_code
       192│ 
   9  /opt/poetry/venv/lib/python3.10/site-packages/cleo/application.py:431 in _run
       429│             io.input.interactive(interactive)
       430│ 
     → 431│         exit_code = self._run_command(command, io)
       432│         self._running_command = None
       433│ 
   8  /opt/poetry/venv/lib/python3.10/site-packages/cleo/application.py:473 in _run_command
       471│ 
       472│         if error is not None:
     → 473│             raise error
       474│ 
       475│         return terminate_event.exit_code
   7  /opt/poetry/venv/lib/python3.10/site-packages/cleo/application.py:457 in _run_command
       455│ 
       456│             if command_event.command_should_run():
     → 457│                 exit_code = command.run(io)
       458│             else:
       459│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED
   6  /opt/poetry/venv/lib/python3.10/site-packages/cleo/commands/base_command.py:117 in run
       115│         io.input.validate()
       116│ 
     → 117│         return self.execute(io) or 0
       118│ 
       119│     def merge_application_definition(self, merge_args: bool = True) -> None:
   5  /opt/poetry/venv/lib/python3.10/site-packages/cleo/commands/command.py:61 in execute
        59│ 
        60│         try:
     →  61│             return self.handle()
        62│         except KeyboardInterrupt:
        63│             return 1
   4  /opt/poetry/venv/lib/python3.10/site-packages/poetry/console/commands/publish.py:82 in handle
        80│         )
        81│ 
     →  82│         publisher.publish(
        83│             self.option("repository"),
        84│             self.option("username"),
   3  /opt/poetry/venv/lib/python3.10/site-packages/poetry/publishing/publisher.py:86 in publish
        84│         )
        85│ 
     →  86│         self._uploader.upload(
        87│             url,
        88│             cert=resolved_cert,
   2  /opt/poetry/venv/lib/python3.10/site-packages/poetry/publishing/uploader.py:107 in upload
       105│ 
       106│         try:
     → 107│             self._upload(session, url, dry_run, skip_existing)
       108│         finally:
       109│             session.close()
   1  /opt/poetry/venv/lib/python3.10/site-packages/poetry/publishing/uploader.py:191 in _upload
       189│     ) -> None:
       190│         for file in self.files:
     → 191│             self._upload_file(session, url, file, dry_run, skip_existing)
       192│ 
       193│     def _upload_file(
  UploadError
  HTTP Error 401:  | b'{\n  "errors" : [ {\n    "status" : 401,\n    "message" : "Wrong username was used"\n  } ]\n}'
  at /opt/poetry/venv/lib/python3.10/site-packages/poetry/publishing/uploader.py:271 in _upload_file
      267│                 if self._io.output.is_decorated():
      268│                     self._io.overwrite(
      269│                         f" - Uploading {file.name} FAILED"
      270│                     )
    → 271│                 raise UploadError(e)
      272│             finally:
      273│                 self._io.write_line("")
      274│ 
      275│     def _register(self, session: requests.Session, url: str) -> requests.Response:
Error: Process completed with exit code 1.

我尝试使用诗歌

http-basic.example
方法,包括用户名
__token_
和密码访问令牌,如pypi文档中所述(https://pypi.org/help/#apitoken),但没有任何运气。同样的问题仍然存在。

- name: Publish to artifactory
        env:
          POETRY_HTTP_BASIC_EXAMPLE_USERNAME: '__token__'
          POETRY_HTTP_BASIC_EXAMPLE_PASSWORD: '${{ steps.fetch_access_token.outputs.access_token }}'
          POETRY_REPOSITORIES_EXAMPLE_URL: 'https://example.jfrog.io/artifactory/api/pypi/pypi-general-local'
        run: |
          cd packages/<package-example>
          sed -i "0,/\(version = \"[0-9]\+.[0-9]\+\)\"/s//\1.${{ github.run_number }}\"/" pyproject.toml
          poetry config http-basic.example $POETRY_HTTP_BASIC_EXAMPLE_USERNAME $POETRY_HTTP_BASIC_EXAMPLE_PASSWORD
          poetry publish --build -r example -vvv
github-actions openid-connect pypi python-poetry
1个回答
0
投票

我设法使用诗歌的

http-basic.example
身份验证方法进行发布工作。
POETRY_HTTP_BASIC_EXAMPLE_USERNAME
必须是与从 Jfrog 获取的访问令牌关联的用户名(在 Jfrog 的 OIDC 集成中的身份方法中设置的用户)

- name: Publish to artifactory
        env:
          POETRY_HTTP_BASIC_EXAMPLE_USERNAME: '${{ vars.<var_name>' }}
          POETRY_HTTP_BASIC_EXAMPLE_PASSWORD: '${{ steps.fetch_access_token.outputs.access_token }}'
          POETRY_REPOSITORIES_EXAMPLE_URL: 'https://example.jfrog.io/artifactory/api/pypi/pypi-general-local'
        run: |
          cd packages/<package-example>
          sed -i "0,/\(version = \"[0-9]\+.[0-9]\+\)\"/s//\1.${{ github.run_number }}\"/" pyproject.toml
          poetry config http-basic.example $POETRY_HTTP_BASIC_EXAMPLE_USERNAME $POETRY_HTTP_BASIC_EXAMPLE_PASSWORD
          poetry publish --build -r example -vvv

我仍然宁愿在 GitHub 网站上仅使用令牌,而不需要指定用户名,但我不太确定这是否可能。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.