chore(ci): black+isort format acr_cleanup.py
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 23s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 43s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m15s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 30s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m18s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 16s
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 35s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m19s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m19s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m18s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 5m1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 6m57s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 17s
AI Code Review / AI Code Review (pull_request) Successful in 7m49s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Failing after 1m31s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m17s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 1275h11m47s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 1275h11m49s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 1275h11m53s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 1275h17m43s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1275h17m59s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1275h21m49s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1275h24m14s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1275h21m49s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1275h24m16s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1275h21m51s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1275h24m18s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 1275h44m25s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 1275h54m24s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 23s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 43s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m15s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 30s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m18s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 16s
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 35s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m19s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m19s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m18s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 5m1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 6m57s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 17s
AI Code Review / AI Code Review (pull_request) Successful in 7m49s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Failing after 1m31s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m17s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 1275h11m47s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 1275h11m49s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 1275h11m53s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 1275h17m43s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1275h17m59s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1275h21m49s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1275h24m14s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1275h21m49s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1275h24m16s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1275h21m51s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1275h24m18s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 1275h44m25s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 1275h54m24s
This commit is contained in:
+15
-15
@@ -72,6 +72,7 @@ ACCEPT_MANIFEST_V2 = "application/vnd.docker.distribution.manifest.v2+json"
|
||||
|
||||
# ========== Registry API ==========
|
||||
|
||||
|
||||
def get_token(repo, action="pull"):
|
||||
"""获取仓库访问token"""
|
||||
scope = "repository:" + NAMESPACE + "/" + repo + ":" + action
|
||||
@@ -201,6 +202,7 @@ def delete_manifest(repo, digest, token):
|
||||
|
||||
# ========== Gitea API ==========
|
||||
|
||||
|
||||
def gitea_get_open_prs():
|
||||
"""获取所有打开的PR编号列表"""
|
||||
if not GITEA_TOKEN:
|
||||
@@ -249,6 +251,7 @@ def gitea_get_pr_commits(pr_number):
|
||||
|
||||
# ========== 工具函数 ==========
|
||||
|
||||
|
||||
def parse_time(created_str):
|
||||
"""解析ISO时间字符串"""
|
||||
if not created_str:
|
||||
@@ -299,6 +302,7 @@ def is_in_protected_list(tag, protected_set):
|
||||
|
||||
# ========== 核心清理逻辑 ==========
|
||||
|
||||
|
||||
def cleanup_repo(repo, keep_count, dry_run, protected_tags, pr_sha=None, pr_open_set=None):
|
||||
"""
|
||||
清理单个仓库
|
||||
@@ -335,7 +339,11 @@ def cleanup_repo(repo, keep_count, dry_run, protected_tags, pr_sha=None, pr_open
|
||||
|
||||
# ========== PR-SHA模式:只删除指定commit的PR镜像 ==========
|
||||
if pr_sha:
|
||||
pr_tags_to_del = [t for t in tags if t.startswith("pr-" + pr_sha) or t == "pr-" + pr_sha or pr_sha.startswith(extract_sha_from_pr_tag(t))]
|
||||
pr_tags_to_del = [
|
||||
t
|
||||
for t in tags
|
||||
if t.startswith("pr-" + pr_sha) or t == "pr-" + pr_sha or pr_sha.startswith(extract_sha_from_pr_tag(t))
|
||||
]
|
||||
if not pr_tags_to_del:
|
||||
print(f" 未找到PR镜像: pr-{pr_sha[:12]}")
|
||||
return len(tags), 0
|
||||
@@ -472,10 +480,7 @@ def cleanup_repo(repo, keep_count, dry_run, protected_tags, pr_sha=None, pr_open
|
||||
# 白名单过滤:受保护的tag不删除
|
||||
if protected_tags:
|
||||
before = len(commit_to_delete)
|
||||
commit_to_delete = [
|
||||
t for t in commit_to_delete
|
||||
if not is_in_protected_list(t["tag"], protected_tags)
|
||||
]
|
||||
commit_to_delete = [t for t in commit_to_delete if not is_in_protected_list(t["tag"], protected_tags)]
|
||||
removed = before - len(commit_to_delete)
|
||||
if removed > 0:
|
||||
print(f" 白名单保护: 跳过{removed}个运行中镜像")
|
||||
@@ -492,10 +497,7 @@ def cleanup_repo(repo, keep_count, dry_run, protected_tags, pr_sha=None, pr_open
|
||||
# 再次过滤白名单(PR镜像也受白名单保护)
|
||||
if protected_tags:
|
||||
before = len(all_to_delete)
|
||||
all_to_delete = [
|
||||
t for t in all_to_delete
|
||||
if not is_in_protected_list(t["tag"], protected_tags)
|
||||
]
|
||||
all_to_delete = [t for t in all_to_delete if not is_in_protected_list(t["tag"], protected_tags)]
|
||||
removed = before - len(all_to_delete)
|
||||
if removed > 0:
|
||||
print(f" 白名单保护(PR镜像): 跳过{removed}个")
|
||||
@@ -549,6 +551,7 @@ def _execute_delete(repo, to_delete, dry_run, total_tags):
|
||||
|
||||
# ========== 主函数 ==========
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="ACR镜像清理工具(增强版)")
|
||||
parser.add_argument("--keep", type=int, default=20, help="保留最近N个commit hash tag(默认20)")
|
||||
@@ -556,10 +559,8 @@ def main():
|
||||
parser.add_argument("--execute", action="store_true", help="实际执行删除")
|
||||
parser.add_argument("--repo", type=str, default="", help="只清理指定仓库")
|
||||
parser.add_argument("--pr-sha", type=str, default="", help="PR关闭模式:删除指定commit sha的PR镜像")
|
||||
parser.add_argument("--protected-tags", type=str, default="",
|
||||
help="受保护tag列表,逗号分隔(运行中镜像白名单)")
|
||||
parser.add_argument("--skip-pr-check", action="store_true",
|
||||
help="跳过Gitea PR状态检查(纯按时间清理PR镜像)")
|
||||
parser.add_argument("--protected-tags", type=str, default="", help="受保护tag列表,逗号分隔(运行中镜像白名单)")
|
||||
parser.add_argument("--skip-pr-check", action="store_true", help="跳过Gitea PR状态检查(纯按时间清理PR镜像)")
|
||||
args = parser.parse_args()
|
||||
|
||||
# 必须指定 --dry-run 或 --execute
|
||||
@@ -632,8 +633,7 @@ def main():
|
||||
total_tags = 0
|
||||
for repo in repos_to_clean:
|
||||
count, deleted = cleanup_repo(
|
||||
repo, args.keep, dry_run, protected_tags,
|
||||
pr_sha=args.pr_sha, pr_open_set=pr_open_set
|
||||
repo, args.keep, dry_run, protected_tags, pr_sha=args.pr_sha, pr_open_set=pr_open_set
|
||||
)
|
||||
total_tags += count
|
||||
total_deleted += deleted
|
||||
|
||||
Reference in New Issue
Block a user