chore: address review findings and exclusions
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"excluded_findings": [
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:10-15",
|
||||||
|
"title": "trim unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:30-59",
|
||||||
|
"title": "resolve_package_names unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:61-76",
|
||||||
|
"title": "parse_repo_context unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:78-120",
|
||||||
|
"title": "api_request unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:122-181",
|
||||||
|
"title": "fetch_package_versions unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:183-241",
|
||||||
|
"title": "collect_package_candidates unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "entrypoint.sh:243-286",
|
||||||
|
"title": "process_candidates unit tests",
|
||||||
|
"reason": "This repository intentionally excludes test fixtures and CI workflows."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -65,3 +65,15 @@ jobs:
|
|||||||
- 不需要新增 `.gitea/workflows/ci.yaml`
|
- 不需要新增 `.gitea/workflows/ci.yaml`
|
||||||
- 不需要新增 `tests/*`
|
- 不需要新增 `tests/*`
|
||||||
- 除非另外明確要求,請不要再補這兩類檔案
|
- 除非另外明確要求,請不要再補這兩類檔案
|
||||||
|
|
||||||
|
## Review Exclusions
|
||||||
|
|
||||||
|
以下審查意見屬於刻意排除,不再以測試或 CI 的形式處理:
|
||||||
|
|
||||||
|
- `entrypoint.sh:10-15` `trim`
|
||||||
|
- `entrypoint.sh:30-59` `resolve_package_names`
|
||||||
|
- `entrypoint.sh:61-76` `parse_repo_context`
|
||||||
|
- `entrypoint.sh:78-120` `api_request`
|
||||||
|
- `entrypoint.sh:122-181` `fetch_package_versions`
|
||||||
|
- `entrypoint.sh:183-241` `collect_package_candidates`
|
||||||
|
- `entrypoint.sh:243-286` `process_candidates`
|
||||||
|
|||||||
+42
-10
@@ -11,13 +11,20 @@ fail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trim() {
|
trim() {
|
||||||
|
# Remove leading and trailing ASCII whitespace from a string.
|
||||||
local value="$1"
|
local value="$1"
|
||||||
value="${value#"${value%%[![:space:]]*}"}"
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
value="${value%"${value##*[![:space:]]}"}"
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
printf '%s' "$value"
|
printf '%s' "$value"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
url_encode() {
|
||||||
|
# URL-encode a single path or query component using jq's RFC 3986 encoding.
|
||||||
|
jq -rn --arg value "$1" '$value|@uri'
|
||||||
|
}
|
||||||
|
|
||||||
resolve_token() {
|
resolve_token() {
|
||||||
|
# Resolve the already-merged token input passed in RUNNER_TOKEN.
|
||||||
log "Trying token from RUNNER_TOKEN"
|
log "Trying token from RUNNER_TOKEN"
|
||||||
|
|
||||||
if [[ -n "${RUNNER_TOKEN:-}" ]]; then
|
if [[ -n "${RUNNER_TOKEN:-}" ]]; then
|
||||||
@@ -30,6 +37,7 @@ resolve_token() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolve_keep_count() {
|
resolve_keep_count() {
|
||||||
|
# Parse KEEP_COUNT and ensure it is a non-negative integer.
|
||||||
local raw_value="${INPUT_KEEP_COUNT:-2}"
|
local raw_value="${INPUT_KEEP_COUNT:-2}"
|
||||||
|
|
||||||
if [[ -z "${raw_value}" ]]; then
|
if [[ -z "${raw_value}" ]]; then
|
||||||
@@ -135,18 +143,26 @@ api_request() {
|
|||||||
|
|
||||||
fetch_package_versions() {
|
fetch_package_versions() {
|
||||||
# Fetch and aggregate all package versions for a single package name.
|
# Fetch and aggregate all package versions for a single package name.
|
||||||
# stdout: JSON array of version objects sorted by page order, later sorted by created_at by the caller.
|
# Params:
|
||||||
|
# $1 owner
|
||||||
|
# $2 package_name
|
||||||
|
# stdout:
|
||||||
|
# JSON array of version objects.
|
||||||
local owner="$1"
|
local owner="$1"
|
||||||
local package_name="$2"
|
local package_name="$2"
|
||||||
local page=1
|
local page=1
|
||||||
local limit=100
|
local limit=100
|
||||||
local aggregate_file page_file headers_file meta http_code status_text request_id page_length path
|
local aggregate_file page_file headers_file meta http_code status_text request_id page_length path
|
||||||
|
local encoded_owner encoded_package_name
|
||||||
|
|
||||||
|
encoded_owner="$(url_encode "${owner}")"
|
||||||
|
encoded_package_name="$(url_encode "${package_name}")"
|
||||||
|
|
||||||
aggregate_file="$(mktemp)"
|
aggregate_file="$(mktemp)"
|
||||||
printf '[]' > "${aggregate_file}"
|
printf '[]' > "${aggregate_file}"
|
||||||
|
|
||||||
while :; do
|
while :; do
|
||||||
path="/api/v1/packages/${owner}/nuget/${package_name}?page=${page}&limit=${limit}"
|
path="/api/v1/packages/${encoded_owner}/nuget/${encoded_package_name}?page=${page}&limit=${limit}"
|
||||||
page_file="$(mktemp)"
|
page_file="$(mktemp)"
|
||||||
headers_file="$(mktemp)"
|
headers_file="$(mktemp)"
|
||||||
meta="$(api_request GET "${path}" "${page_file}" "${headers_file}")"
|
meta="$(api_request GET "${path}" "${page_file}" "${headers_file}")"
|
||||||
@@ -184,7 +200,13 @@ fetch_package_versions() {
|
|||||||
|
|
||||||
collect_package_candidates() {
|
collect_package_candidates() {
|
||||||
# Build the delete candidate file for the requested package names.
|
# Build the delete candidate file for the requested package names.
|
||||||
# stdout: package_count<TAB>total_version_count<TAB>kept_count<TAB>candidate_count
|
# Params:
|
||||||
|
# $1 owner
|
||||||
|
# $2 keep_count
|
||||||
|
# $3 candidate_file
|
||||||
|
# $4... package names
|
||||||
|
# stdout:
|
||||||
|
# package_count<TAB>total_version_count<TAB>kept_count<TAB>candidate_count
|
||||||
local owner="$1"
|
local owner="$1"
|
||||||
local keep_count="$2"
|
local keep_count="$2"
|
||||||
local candidate_file="$3"
|
local candidate_file="$3"
|
||||||
@@ -215,7 +237,7 @@ collect_package_candidates() {
|
|||||||
while IFS=$'\t' read -r version created_at; do
|
while IFS=$'\t' read -r version created_at; do
|
||||||
[[ -z "${version}" ]] && continue
|
[[ -z "${version}" ]] && continue
|
||||||
log " - ${version} (${created_at})"
|
log " - ${version} (${created_at})"
|
||||||
done < <(jq -r 'sort_by(.created_at)[] | [.version, .created_at] | @tsv' <<<"${versions_json}")
|
done < <(jq -r 'sort_by(.created_at, .version)[] | [.version, .created_at] | @tsv' <<<"${versions_json}")
|
||||||
|
|
||||||
if (( total_versions <= keep_count )); then
|
if (( total_versions <= keep_count )); then
|
||||||
log " keep all ${total_versions} versions"
|
log " keep all ${total_versions} versions"
|
||||||
@@ -226,7 +248,7 @@ collect_package_candidates() {
|
|||||||
kept_count=$((kept_count + keep_count))
|
kept_count=$((kept_count + keep_count))
|
||||||
candidates_json="$(
|
candidates_json="$(
|
||||||
jq -c --argjson keep "${keep_count}" \
|
jq -c --argjson keep "${keep_count}" \
|
||||||
'sort_by(.created_at) | .[0:(length - $keep)]' <<<"${versions_json}"
|
'sort_by(.created_at, .version) | .[0:(length - $keep)]' <<<"${versions_json}"
|
||||||
)"
|
)"
|
||||||
|
|
||||||
while IFS=$'\t' read -r package version created_at; do
|
while IFS=$'\t' read -r package version created_at; do
|
||||||
@@ -242,6 +264,13 @@ collect_package_candidates() {
|
|||||||
|
|
||||||
process_candidates() {
|
process_candidates() {
|
||||||
# Delete each queued version and summarize the result.
|
# Delete each queued version and summarize the result.
|
||||||
|
# Params:
|
||||||
|
# $1 owner
|
||||||
|
# $2 candidate_file
|
||||||
|
# $3 package_count
|
||||||
|
# $4 total_version_count
|
||||||
|
# $5 kept_count
|
||||||
|
# $6 candidate_count
|
||||||
local owner="$1"
|
local owner="$1"
|
||||||
local candidate_file="$2"
|
local candidate_file="$2"
|
||||||
local package_count="$3"
|
local package_count="$3"
|
||||||
@@ -250,7 +279,7 @@ process_candidates() {
|
|||||||
local candidate_count="$6"
|
local candidate_count="$6"
|
||||||
local deleted_count=0
|
local deleted_count=0
|
||||||
local error_count=0
|
local error_count=0
|
||||||
local package_name version created_at
|
local package_name version _created_at
|
||||||
local body_file headers_file meta http_code status_text request_id
|
local body_file headers_file meta http_code status_text request_id
|
||||||
|
|
||||||
if [[ ! -s "${candidate_file}" ]]; then
|
if [[ ! -s "${candidate_file}" ]]; then
|
||||||
@@ -259,12 +288,12 @@ process_candidates() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
while IFS=$'\t' read -r package_name version created_at; do
|
while IFS=$'\t' read -r package_name version _created_at; do
|
||||||
[[ -z "${package_name}" ]] && continue
|
[[ -z "${package_name}" ]] && continue
|
||||||
|
|
||||||
body_file="$(mktemp)"
|
body_file="$(mktemp)"
|
||||||
headers_file="$(mktemp)"
|
headers_file="$(mktemp)"
|
||||||
meta="$(api_request DELETE "/api/v1/packages/${owner}/nuget/${package_name}/${version}" "${body_file}" "${headers_file}")"
|
meta="$(api_request DELETE "/api/v1/packages/$(url_encode "${owner}")/nuget/$(url_encode "${package_name}")/$(url_encode "${version}")" "${body_file}" "${headers_file}")"
|
||||||
IFS=$'\t' read -r http_code status_text request_id <<< "${meta}"
|
IFS=$'\t' read -r http_code status_text request_id <<< "${meta}"
|
||||||
rm -f "${body_file}" "${headers_file}"
|
rm -f "${body_file}" "${headers_file}"
|
||||||
|
|
||||||
@@ -285,7 +314,10 @@ process_candidates() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
local token keep_count repository owner repo package_names_csv
|
# Entry point for the Docker container. Resolves inputs, builds candidates,
|
||||||
|
# and applies deletes for the selected NuGet packages.
|
||||||
|
local token keep_count repository owner _repo package_names_csv
|
||||||
|
local -a package_names
|
||||||
local candidate_file summary package_count total_version_count kept_count candidate_count
|
local candidate_file summary package_count total_version_count kept_count candidate_count
|
||||||
|
|
||||||
log "Gitea Server Url: ${GITEA_SERVER_URL:-}"
|
log "Gitea Server Url: ${GITEA_SERVER_URL:-}"
|
||||||
@@ -298,7 +330,7 @@ main() {
|
|||||||
export RESOLVED_GITEA_TOKEN="$token"
|
export RESOLVED_GITEA_TOKEN="$token"
|
||||||
|
|
||||||
repository="${GITEA_REPOSITORY:-}"
|
repository="${GITEA_REPOSITORY:-}"
|
||||||
IFS=$'\t' read -r owner repo <<< "$(parse_repo_context "${repository}")"
|
IFS=$'\t' read -r owner _repo <<< "$(parse_repo_context "${repository}")"
|
||||||
keep_count="$(resolve_keep_count)"
|
keep_count="$(resolve_keep_count)"
|
||||||
|
|
||||||
mapfile -t package_names < <(resolve_package_names)
|
mapfile -t package_names < <(resolve_package_names)
|
||||||
|
|||||||
Reference in New Issue
Block a user