feat: support package name filtering and refactor cleanup flow

This commit is contained in:
2026-05-15 02:50:38 +00:00
parent 3305b57ac0
commit 528f8c75b3
5 changed files with 403 additions and 107 deletions
+223
View File
@@ -0,0 +1,223 @@
#!/bin/bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "${TMP_DIR}"' EXIT
assert_eq() {
local expected="$1"
local actual="$2"
if [[ "${expected}" != "${actual}" ]]; then
printf 'Expected:\n%s\nActual:\n%s\n' "${expected}" "${actual}" >&2
exit 1
fi
}
expect_fail() {
if ( "$@" ) >/dev/null 2>&1; then
printf 'Expected failure: %s\n' "$*" >&2
exit 1
fi
}
write_mock_curl_pagination() {
cat > "${TMP_DIR}/curl" <<'EOF'
#!/bin/sh
make_versions_json() {
prefix="$1"
start="$2"
count="$3"
i=0
printf '['
while [ "$i" -lt "$count" ]; do
idx=$((start + i))
[ "$i" -gt 0 ] && printf ','
printf '{"name":"%s","version":"%s.%s.0","created_at":"2023-01-%02dT00:00:00Z"}' \
"$prefix" "$idx" "$idx" "$((idx + 1))"
i=$((i + 1))
done
printf ']'
}
method=GET
out_file=
headers_file=
url=
while [ "$#" -gt 0 ]; do
case "$1" in
-X) method=$2; shift 2 ;;
-D) headers_file=$2; shift 2 ;;
-o) out_file=$2; shift 2 ;;
-w) shift 2 ;;
-H|-sS) shift 1 ;;
*) url=$1; shift ;;
esac
done
body='[]'
status='HTTP/1.1 200 OK'
case "$url" in
*'/api/v1/packages/test-owner/nuget/pkg-a?page=1&limit=100')
body="$(make_versions_json pkg-a 0 100)"
;;
*'/api/v1/packages/test-owner/nuget/pkg-a?page=2&limit=100')
body="$(make_versions_json pkg-a 100 1)"
;;
esac
printf '%s' "$body" > "$out_file"
{
printf '%s\n' "$status"
printf 'X-Request-Id: req-page\n'
} > "$headers_file"
printf '%s' 200
EOF
chmod +x "${TMP_DIR}/curl"
}
write_mock_curl_collect() {
cat > "${TMP_DIR}/curl" <<'EOF'
#!/bin/sh
method=GET
out_file=
headers_file=
url=
while [ "$#" -gt 0 ]; do
case "$1" in
-X) method=$2; shift 2 ;;
-D) headers_file=$2; shift 2 ;;
-o) out_file=$2; shift 2 ;;
-w) shift 2 ;;
-H|-sS) shift 1 ;;
*) url=$1; shift ;;
esac
done
body='[]'
status='HTTP/1.1 200 OK'
code='200'
case "$url" in
*'/api/v1/packages/test-owner/nuget/pkg-a?page=1&limit=100')
body='[{"name":"pkg-a","version":"1.0.0","created_at":"2023-01-01T00:00:00Z"},{"name":"pkg-a","version":"1.1.0","created_at":"2023-01-02T00:00:00Z"},{"name":"pkg-a","version":"1.2.0","created_at":"2023-01-03T00:00:00Z"}]'
;;
*'/api/v1/packages/test-owner/nuget/pkg-b?page=1&limit=100')
code='404'
status='HTTP/1.1 404 Not Found'
body=''
;;
esac
printf '%s' "$body" > "$out_file"
{
printf '%s\n' "$status"
printf 'X-Request-Id: req-collect\n'
} > "$headers_file"
printf '%s' "$code"
EOF
chmod +x "${TMP_DIR}/curl"
}
write_mock_curl_delete() {
cat > "${TMP_DIR}/curl" <<'EOF'
#!/bin/sh
method=GET
out_file=
headers_file=
url=
while [ "$#" -gt 0 ]; do
case "$1" in
-X) method=$2; shift 2 ;;
-D) headers_file=$2; shift 2 ;;
-o) out_file=$2; shift 2 ;;
-w) shift 2 ;;
-H|-sS) shift 1 ;;
*) url=$1; shift ;;
esac
done
code='200'
status='HTTP/1.1 200 OK'
body='[]'
case "$url" in
*'/api/v1/packages/test-owner/nuget/pkg-a?page=1&limit=100')
body='[{"name":"pkg-a","version":"1.0.0","created_at":"2023-01-01T00:00:00Z"},{"name":"pkg-a","version":"0.9.0","created_at":"2022-12-31T00:00:00Z"}]'
;;
*'/api/v1/packages/test-owner/nuget/pkg-a/1.0.0')
if [ "$method" = "DELETE" ]; then
code='204'
status='HTTP/1.1 204 No Content'
body=''
fi
;;
*'/api/v1/packages/test-owner/nuget/pkg-a/0.9.0')
if [ "$method" = "DELETE" ]; then
code='404'
status='HTTP/1.1 404 Not Found'
body=''
fi
;;
esac
printf '%s' "$body" > "$out_file"
{
printf '%s\n' "$status"
printf 'X-Request-Id: req-delete\n'
} > "$headers_file"
if [ "$method" = "DELETE" ] && [ -n "${MOCK_DELETE_LOG:-}" ]; then
printf '%s %s\n' "$method" "$url" >> "$MOCK_DELETE_LOG"
fi
printf '%s' "$code"
EOF
chmod +x "${TMP_DIR}/curl"
}
source "${ROOT_DIR}/entrypoint.sh"
assert_eq "abc" "$(RUNNER_TOKEN=abc resolve_token)"
expect_fail env -u RUNNER_TOKEN bash -lc "source '${ROOT_DIR}/entrypoint.sh'; resolve_token"
assert_eq "5" "$(INPUT_KEEP_COUNT=5 resolve_keep_count)"
expect_fail env INPUT_KEEP_COUNT=abc bash -lc "source '${ROOT_DIR}/entrypoint.sh'; resolve_keep_count"
output="$(INPUT_PACKAGE_NAMES=$' pkg-a, pkg-b\npkg-a , pkg-c ' resolve_package_names)"
assert_eq $'pkg-a\npkg-b\npkg-c' "${output}"
expect_fail env INPUT_PACKAGE_NAMES=' , ' bash -lc "source '${ROOT_DIR}/entrypoint.sh'; resolve_package_names"
IFS=$'\t' read -r owner repo <<< "$(parse_repo_context "owner/repo")"
assert_eq "owner" "${owner}"
assert_eq "repo" "${repo}"
expect_fail bash -lc "source '${ROOT_DIR}/entrypoint.sh'; parse_repo_context 'repo'"
write_mock_curl_pagination
output="$(PATH="${TMP_DIR}:$PATH" GITEA_SERVER_URL="https://gitea.example.com" RESOLVED_GITEA_TOKEN="token" \
fetch_package_versions "test-owner" "pkg-a")"
assert_eq "101" "$(jq 'length' <<<"${output}")"
assert_eq "0.0.0" "$(jq -r '.[0].version' <<<"${output}")"
assert_eq "100.100.0" "$(jq -r '.[100].version' <<<"${output}")"
write_mock_curl_collect
summary="$(PATH="${TMP_DIR}:$PATH" GITEA_SERVER_URL="https://gitea.example.com" RESOLVED_GITEA_TOKEN="token" \
collect_package_candidates "test-owner" "1" "${TMP_DIR}/candidates.tsv" "pkg-a" "pkg-b")"
IFS=$'\t' read -r package_count total_version_count kept_count candidate_count <<< "${summary}"
assert_eq "1" "${package_count}"
assert_eq "3" "${total_version_count}"
assert_eq "1" "${kept_count}"
assert_eq "2" "${candidate_count}"
assert_eq "2" "$(wc -l < "${TMP_DIR}/candidates.tsv" | tr -d ' ')"
write_mock_curl_delete
candidate_file="${TMP_DIR}/delete.tsv"
cat > "${candidate_file}" <<'EOF'
pkg-a 1.0.0 2023-01-01T00:00:00Z
pkg-a 0.9.0 2022-12-31T00:00:00Z
EOF
output="$(MOCK_DELETE_LOG="${TMP_DIR}/delete.log" PATH="${TMP_DIR}:$PATH" GITEA_SERVER_URL="https://gitea.example.com" RESOLVED_GITEA_TOKEN="token" \
process_candidates "test-owner" "${candidate_file}" "1" "2" "1" "2" 2>&1)"
assert_eq "1" "$(grep -c '^DELETE ' "${TMP_DIR}/delete.log")"
assert_eq "Summary: packages=1 versions=2 kept=1 candidates=2 deleted=1 errors=1" "$(printf '%s' "${output}" | tail -n 1)"