fixed testpypi upload
This commit is contained in:
+69
-6
@@ -155,7 +155,7 @@ python build/run.py release github --version 0.5.2 --apply # 执行
|
||||
|
||||
其他开关:`--notes-file`(自定义 release notes)、`--attach-preflight`(把 `preflight.json` 也作为附件上传,便于审计;注意报告里有本机绝对路径)、`--allow-dirty-release`、`--skip-fetch`、`--skip-checks`。
|
||||
|
||||
> tag 拼写沿用历史风格 `v<version>`(注意历史里那个 typo tag `0.50` 指向 `v0.5.1`)。命令会在动手前拒绝已存在的 tag,所以不会重复发布。
|
||||
> tag 拼写沿用历史风格 `v<version>`(注意历史里那个 typo tag `0.50` 指向 `v0.5.1`)。命令会在动手前拒绝已存在的 tag,所以不会重复发布。**如果 tag 已经 push 但 Release 上传失败(例如 `gh` 没配好),直接重跑同一条 `--apply` 命令即可续跑**:它会跳过创建 tag,只补做剩下的步骤;只有「GitHub Release 已存在」才拒绝。
|
||||
|
||||
### 3.2 PyPI:TestPyPI 先行,确认后再上正式仓库
|
||||
|
||||
@@ -163,19 +163,82 @@ python build/run.py release github --version 0.5.2 --apply # 执行
|
||||
python build/run.py release pypi --version 0.5.2 # 预览
|
||||
python build/run.py release pypi --version 0.5.2 --apply # 只发 TestPyPI
|
||||
python build/run.py release pypi --version 0.5.2 --confirm-pypi --apply # TestPyPI + 正式 PyPI
|
||||
|
||||
# 只有正式 token、没有 TestPyPI 账号时:跳过彩排直接发正式库
|
||||
python build/run.py release pypi --version 0.5.2 --pypi-only --apply
|
||||
```
|
||||
|
||||
`--pypi-only` 与 `--confirm-pypi` 互斥。**注意它的代价**:没有 TestPyPI 彩排,而正式库的版本号一旦占用就无法复用、无法替换。它仍然会做完整门禁、`twine check`、上传前查重、上传后回读索引核对文件、以及把产物重新拉回来验证。
|
||||
|
||||
执行顺序:
|
||||
|
||||
1. 同样的证书校验
|
||||
1. 认证书校验(与 `release github` 同一份报告)
|
||||
2. `twine check` 全部 wheel(校验 METADATA/long description,上传前就能发现问题)
|
||||
3. 只读查询目标索引,确认该版本不存在(TestPyPI 与 PyPI 各查各的)
|
||||
4. 上传 TestPyPI → 回读索引确认 6 个文件都在 → `pip download` 把刚上传的 wheel 拉回来,证明产物可获取
|
||||
5. 只有加了 `--confirm-pypi` 才会对正式 PyPI 重复第 3-4 步;否则停在这里并打印后续命令
|
||||
4. 上传 → 回读索引确认 6 个文件都在 → `pip download` 把刚上传的 wheel 拉回来,证明产物可获取
|
||||
5. 未加 `--confirm-pypi` 时只发 TestPyPI,然后停在这里并打印后续命令
|
||||
|
||||
凭证由 twine 自己解析:`~/.pypirc` 的 `[testpypi]` / `[pypi]` 段,或 `TWINE_USERNAME=__token__` + `TWINE_PASSWORD=<token>`。命令会在**任何写操作之前**检查凭证是否配置好并给出提示。**不要把 token 写进仓库。**
|
||||
### 3.3 凭证:`release auth` 与 `~/.pypirc`
|
||||
|
||||
### 3.3 已知的历史发布空洞
|
||||
```powershell
|
||||
python build/run.py release auth # 查看两个索引的凭证状态
|
||||
python build/run.py release auth --set-token pypi # 隐藏输入,写入 ~/.pypirc
|
||||
python build/run.py release auth --set-token testpypi
|
||||
python build/run.py release auth --repair # 修「有段但没列进 index-servers」
|
||||
```
|
||||
|
||||
`--set-token` 的 token 只从**隐藏输入**或 `--token-stdin`(供脚本/CI)读取,**不接受命令行参数**——避免落进 shell 历史和进程列表。写入采用定点文本编辑,文件里的说明注释会保留;同时会把该索引补进 `[distutils] index-servers`(这一步很关键,见下)。
|
||||
|
||||
`release auth` 只有在你真的运行 `--set-token` 时才写文件;不带参数时只读并报告,状态判断比「文件是否存在」严格:
|
||||
|
||||
```
|
||||
config file: C:\Users\cheun\.pypirc (exists)
|
||||
[-- ] [pypi] not usable: [pypi] still contains a placeholder token
|
||||
[-- ] [testpypi] not usable: C:\Users\cheun\.pypirc has no [testpypi] section
|
||||
```
|
||||
|
||||
**占位符、空密码、`username` 不是 `__token__`,都会被判定为「不可用」**——否则 twine 只会在真正上传时才发现,而那时已经动过索引了。
|
||||
|
||||
`release pypi` 在 `--apply` 时若凭证缺失:有终端就地提示输入(隐藏),无终端则直接失败并打印 `release auth --set-token <index>`;也可显式加 `--prompt-credentials`。dry run 只告警并继续展示计划,不会卡在输入上。
|
||||
|
||||
#### twine 直接读取的格式
|
||||
|
||||
默认路径 `~/.pypirc`(Windows 上即 `C:\Users\<你>\.pypirc`,由 `USERPROFILE` 展开)。**没有**环境变量可以改这个路径;要用别的文件就传 `--config-file`。
|
||||
|
||||
```ini
|
||||
[distutils]
|
||||
index-servers =
|
||||
pypi
|
||||
testpypi
|
||||
|
||||
[pypi]
|
||||
repository = https://upload.pypi.org/legacy/
|
||||
username = __token__
|
||||
password = pypi-你的正式token
|
||||
|
||||
[testpypi]
|
||||
repository = https://test.pypi.org/legacy/
|
||||
username = __token__
|
||||
password = pypi-你的TestPyPI token
|
||||
```
|
||||
|
||||
容易搞错的点:
|
||||
|
||||
- **`[distutils] index-servers` 必须列出该索引,否则 twine 完全忽略那一节** —— 这是最常见的坑:文件里明明有 `[testpypi]` 段,twine 却报 `InvalidConfiguration: Missing 'testpypi' section`。用 `release auth --repair` 修(把已存在但未列出的段补进 `index-servers`)。
|
||||
- 更细的语义差别:`index-servers =` **值为空**表示「一个都不认」;只有**整行缺失**时 twine 才会回退到默认的 `pypi testpypi`。所以手工编辑时别把名字删空。
|
||||
- `username` 就是字面量 `__token__`,不是账号名或邮箱
|
||||
- 两类 token **都以 `pypi-` 开头**,但**不能互换**:拿正式 token 打 `test.pypi.org` 会被 403 拒绝
|
||||
- TestPyPI 是**独立服务、独立账号**,注册在 <https://test.pypi.org/account/register/>,你的 PyPI 账号在那里不存在
|
||||
- 正式 token 建议限定到 `orisys` 项目(项目已存在,可以建 project-scoped token)
|
||||
- 该文件必须在**任何 git 仓库之外**(放在用户目录里);token 一旦提交进仓库,即使后来删文件也还在历史里——那属于安全事故
|
||||
- 临时替代方案:会话内设 `TWINE_USERNAME=__token__` + `TWINE_PASSWORD=<token>`,命令会识别这种情形
|
||||
- PyPI token **没有只读的校验方式**,有效性只能在真正上传时才会被索引确认;所以所有本地检查、查重都排在写操作之前
|
||||
|
||||
`release auth` 的「可用」判定**直接问 twine 自己**(`twine.utils.get_config` 解析出的 username/password),而不是自己解析 ini,这样报告结果与 twine 的行为不会分叉。twine 未安装时才回退到本地复刻同一套规则。
|
||||
|
||||
只需要 TestPyPI 时才把 `testpypi` 写进 `index-servers` 并填对应 token;只发正式库时 `--pypi-only` 用不到 `[testpypi]` 段。
|
||||
|
||||
### 3.4 已知的历史发布空洞
|
||||
|
||||
| 版本 | 本地 `SDK/` | PyPI | GitHub Release |
|
||||
| --- | --- | --- | --- |
|
||||
|
||||
Reference in New Issue
Block a user