Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c108bfd64 |
@@ -341,3 +341,51 @@ jobs:
|
||||
throw "release asset mismatch: $($publishedNames -join ', ')"
|
||||
}
|
||||
Write-Host "release verified: $tag ($($localNames.Count) files)"
|
||||
|
||||
- name: Publish packages to Gitea PyPI
|
||||
shell: pwsh
|
||||
env:
|
||||
TWINE_USERNAME: antior
|
||||
TWINE_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
||||
TWINE_REPOSITORY_URL: ${{ gitea.server_url }}/api/packages/antior/pypi
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ([string]::IsNullOrWhiteSpace($env:TWINE_PASSWORD)) {
|
||||
throw "GITHUB_TOKEN is required to publish packages"
|
||||
}
|
||||
$headers = @{ Authorization = "token $env:TWINE_PASSWORD" }
|
||||
$simpleUrl = "$env:TWINE_REPOSITORY_URL/simple/dlp-io/"
|
||||
|
||||
function Get-RegistryFileNames {
|
||||
try {
|
||||
$response = Invoke-WebRequest -Headers $headers -Uri $simpleUrl
|
||||
} catch {
|
||||
if ([int]$_.Exception.Response.StatusCode -eq 404) { return @() }
|
||||
throw
|
||||
}
|
||||
return @([regex]::Matches($response.Content, '<a\s+href="[^"]+"[^>]*>(?<name>[^<]+)</a>', "IgnoreCase") |
|
||||
ForEach-Object { [Net.WebUtility]::HtmlDecode($_.Groups["name"].Value) })
|
||||
}
|
||||
|
||||
$published = @(Get-RegistryFileNames)
|
||||
$missing = @(Get-ChildItem -LiteralPath dist -File | Where-Object { $published -notcontains $_.Name })
|
||||
if ($missing.Count -gt 0) {
|
||||
$uploadArgs = @("-3.13", "-m", "twine", "upload", "--non-interactive", "--disable-progress-bar") +
|
||||
@($missing | ForEach-Object FullName)
|
||||
& py @uploadArgs
|
||||
if ($LASTEXITCODE -ne 0) { throw "twine upload failed" }
|
||||
} else {
|
||||
Write-Host "all registry artifacts already published"
|
||||
}
|
||||
|
||||
$expected = @(Get-ChildItem -LiteralPath dist -File | ForEach-Object Name)
|
||||
for ($attempt = 1; $attempt -le 20; $attempt++) {
|
||||
$published = @(Get-RegistryFileNames)
|
||||
$unpublished = @($expected | Where-Object { $published -notcontains $_ })
|
||||
if ($unpublished.Count -eq 0) { break }
|
||||
if ($attempt -lt 20) { Start-Sleep -Seconds 3 }
|
||||
}
|
||||
if ($unpublished.Count -ne 0) {
|
||||
throw "registry package files missing after upload: $($unpublished -join ', ')"
|
||||
}
|
||||
Write-Host "registry verified: dlp-io==$($env:DLP_IO_PACKAGE_VERSION) ($($expected.Count) files)"
|
||||
|
||||
@@ -20,6 +20,8 @@ pytest
|
||||
- `dlp_io-X.Y.Z.tar.gz`(sdist)
|
||||
- `dlp_io.py` 和 5 个裸 `dlp_io.cp3XX-win_amd64.pyd`(免安装单文件,放进项目目录即可 import)
|
||||
|
||||
同一批 wheel/sdist 还会同步发布到 Gitea PyPI registry(`https://gitea.docker.antior.cn/api/packages/antior/pypi/simple`),可直接 `pip install --index-url ... dlp-io`。
|
||||
|
||||
安装方式见 [docs/DLP_IO_LIBRARY.md](docs/DLP_IO_LIBRARY.md)。
|
||||
|
||||
本地只构建纯 Python 版:
|
||||
|
||||
@@ -17,7 +17,7 @@ from enum import Enum
|
||||
from multiprocessing.context import AuthenticationError
|
||||
from multiprocessing.connection import Client
|
||||
|
||||
__version__ = "0.1.0"
|
||||
__version__ = "0.1.1"
|
||||
|
||||
__all__ = [
|
||||
"DlpConfig",
|
||||
|
||||
+17
-5
@@ -2,11 +2,23 @@
|
||||
|
||||
`dlp-io` 为 Windows DLP 透明加密环境提供接近 `io.open` 的 Python 文件 API。非白名单进程负责业务逻辑和写入;文件读取由已获 DLP 白名单授权的 Python helper 完成,再通过经过认证的 Windows Named Pipe 返回明文字节。
|
||||
|
||||
当前版本为 `dlp-io==0.1.0`,distribution 名是 `dlp-io`,import 名是 `dlp_io`。
|
||||
当前版本为 `dlp-io==0.1.1`,distribution 名是 `dlp-io`,import 名是 `dlp_io`。
|
||||
|
||||
## 安装
|
||||
|
||||
发布物托管在 Gitea Release 页面,由 `.gitea/workflows/publish-dlp-io.yaml` 从 immutable tag `dlp-io-vX.Y.Z` 自动构建并上传,全部产物在 CI runner 上编译,不依赖本地环境。
|
||||
### 方式一:Gitea PyPI registry(推荐)
|
||||
|
||||
registry 已开放匿名下载,一条命令即可安装;pip 会自动选择最匹配的 wheel:Windows 上 CPython 3.10–3.14 会得到对应的 pyd wheel(整个库编译为单个 `.pyd`),其余环境得到纯 Python wheel。
|
||||
|
||||
```powershell
|
||||
py -m pip install --index-url https://gitea.docker.antior.cn/api/packages/antior/pypi/simple dlp-io==0.1.1
|
||||
```
|
||||
|
||||
Package 页面:<https://gitea.docker.antior.cn/antior/-/packages/pypi/dlp-io>
|
||||
|
||||
### 方式二:Gitea Release 页面
|
||||
|
||||
发布物由 `.gitea/workflows/publish-dlp-io.yaml` 从 immutable tag `dlp-io-vX.Y.Z` 自动构建并上传,全部产物在 CI runner 上编译,不依赖本地环境。
|
||||
|
||||
Release 页面:<https://gitea.docker.antior.cn/antior/dlp-io/releases>
|
||||
|
||||
@@ -21,13 +33,13 @@ Release 页面:<https://gitea.docker.antior.cn/antior/dlp-io/releases>
|
||||
|
||||
```powershell
|
||||
# 纯 Python 版(任意平台)
|
||||
py -m pip install https://gitea.docker.antior.cn/antior/dlp-io/releases/download/dlp-io-v0.1.0/dlp_io-0.1.0-py3-none-any.whl
|
||||
py -m pip install https://gitea.docker.antior.cn/antior/dlp-io/releases/download/dlp-io-v0.1.1/dlp_io-0.1.1-py3-none-any.whl
|
||||
|
||||
# pyd 版(示例为 CPython 3.13,其它版本替换文件名中的 cp313)
|
||||
py -3.13 -m pip install https://gitea.docker.antior.cn/antior/dlp-io/releases/download/dlp-io-v0.1.0/dlp_io-0.1.0-cp313-cp313-win_amd64.whl
|
||||
py -3.13 -m pip install https://gitea.docker.antior.cn/antior/dlp-io/releases/download/dlp-io-v0.1.1/dlp_io-0.1.1-cp313-cp313-win_amd64.whl
|
||||
```
|
||||
|
||||
也可以先从 Release 页面下载 wheel,再 `py -m pip install <文件路径>`。下载 Release 资产不需要 token;发布只能在 CI 中通过注入的 `GITHUB_TOKEN` 完成,发布凭据不得写入命令行、URL 或 tracked 文件。
|
||||
也可以先从 Release 页面下载 wheel,再 `py -m pip install <文件路径>`。下载 Release 资产和 registry 包都不需要 token;发布只能在 CI 中通过注入的 `GITHUB_TOKEN` 完成,发布凭据不得写入命令行、URL 或 tracked 文件。
|
||||
|
||||
调用方需要安装 `dlp-io`。白名单 Python 无需安装该包:helper 源码由调用方以 UTF-8 通过 stdin 注入,且只依赖 Python 标准库,不会在磁盘创建临时 `.py` 文件。
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ class WorkflowStep(Enum):
|
||||
BUILD = "Build and check distribution"
|
||||
SMOKE = "Smoke test release artifacts"
|
||||
RELEASE = "Create Gitea release with wheels"
|
||||
PYPI = "Publish packages to Gitea PyPI"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
||||
Reference in New Issue
Block a user