mirror of
https://codeberg.org/JasterV/docker.git
synced 2026-04-26 18:10:02 +00:00
203 lines
6.9 KiB
Bash
Executable file
203 lines
6.9 KiB
Bash
Executable file
#!/bin/sh
|
|
set -e
|
|
|
|
# Global Configuration
|
|
TOKEN="${PLUGIN_TOKEN}"
|
|
CRATES_TOKEN="${PLUGIN_CRATES_IO_TOKEN}"
|
|
REPO_FULL_NAME="${CI_REPO}"
|
|
API_URL="https://codeberg.org/api/v1/repos/${REPO_FULL_NAME}"
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Gets a list of all packages in the workspace in topological order.
|
|
# This ensures that "leaves" (dependencies) are listed before the
|
|
# projects that rely on them, so they get published first.
|
|
#
|
|
# Arguments: None
|
|
#
|
|
# Returns: A space/newline separated list of crate names.
|
|
# ------------------------------------------------------------------------------
|
|
get_ordered_crates() {
|
|
# 'cargo tree' lists dependencies.
|
|
# 'awk' extracts just the package name.
|
|
# 'tac' reverses the output list so dependencies are at the top.
|
|
cargo tree --workspace --depth 0 --prefix none --format "{p}" | awk '{print $1}' | tac
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Gathers metadata (name, version) for all packages that
|
|
# are allowed to be published, keeping the required build order.
|
|
#
|
|
# Arguments:
|
|
# $1 - The ordered list of crate names (output of get_ordered_crates)
|
|
#
|
|
# Returns: A list of packages in the format: "name version"
|
|
# ------------------------------------------------------------------------------
|
|
get_publishable_packages() {
|
|
local ordered_names="$1"
|
|
|
|
cargo metadata --format-version 1 --no-deps | jq -r --arg names "$ordered_names" '
|
|
($names | split("\n")) as $order
|
|
| [.packages[] | select(.publish != [])] as $pkgs
|
|
| $order[] as $name
|
|
| $pkgs[] | select(.name == $name)
|
|
| "\(.name) \(.version)"
|
|
'
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Checks the public crates.io API to see if a specific version of a package already exists.
|
|
#
|
|
# Arguments:
|
|
# $1 - Package name
|
|
# $2 - Package version
|
|
#
|
|
# Returns: 0 (Success/True) if it exists, 1 (Failure/False) if it does not.
|
|
# ------------------------------------------------------------------------------
|
|
is_published_on_crates_io() {
|
|
local pkg_name="$1"
|
|
local pkg_version="$2"
|
|
local status_code
|
|
|
|
status_code=$(curl -s -o /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/${pkg_name}/${pkg_version}")
|
|
|
|
if [ "$status_code" = "200" ]; then
|
|
return 0 # True: It is already published
|
|
else
|
|
return 1 # False: It is not published yet
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Checks if a Git tag exists for the release.
|
|
# If it doesn't, it creates the tag locally and pushes it to the remote repository.
|
|
#
|
|
# Arguments:
|
|
# $1 - The tag name (e.g., my-crate-v1.0.0)
|
|
# ------------------------------------------------------------------------------
|
|
ensure_git_tag() {
|
|
local tag_name="$1"
|
|
|
|
# "rev-parse" quietly checks if the tag exists locally or remotely
|
|
if git rev-parse "$tag_name" >/dev/null 2>&1; then
|
|
echo " - Tag $tag_name already exists locally/remotely."
|
|
else
|
|
echo " - Tagging $tag_name..."
|
|
git tag "$tag_name"
|
|
|
|
# Push the tag to Codeberg using the CI token for authentication
|
|
git push "https://$TOKEN@codeberg.org/${REPO_FULL_NAME}.git" "$tag_name"
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Creates a GitHub/Codeberg-style release block on the repository page.
|
|
# It checks the API first to prevent duplicate "409" errors.
|
|
#
|
|
# Arguments:
|
|
# $1 - The tag name (e.g., my-crate-v1.0.0)
|
|
# $2 - Package name
|
|
# $3 - Package version
|
|
# ------------------------------------------------------------------------------
|
|
ensure_codeberg_release() {
|
|
local tag_name="$1"
|
|
local pkg_name="$2"
|
|
local pkg_version="$3"
|
|
local release_check
|
|
local release_payload
|
|
|
|
# Query the API to see if a release already exists for this tag
|
|
release_check=$(curl -s -H "Authorization: token $TOKEN" "$API_URL/releases/tags/$tag_name")
|
|
|
|
if echo "$release_check" | grep -q "\"id\":"; then
|
|
echo " - Codeberg release for $tag_name already exists."
|
|
else
|
|
echo " - Creating Codeberg release for $tag_name..."
|
|
|
|
# Create a multi-line JSON string containing the release details
|
|
release_payload=$(cat <<EOF
|
|
{
|
|
"tag_name": "$tag_name",
|
|
"name": "$pkg_name v$pkg_version",
|
|
"body": "Automated release for crate **$pkg_name** at version \`$pkg_version\`.\n\nSee CHANGELOG.md for details.",
|
|
"draft": false,
|
|
"prerelease": false
|
|
}
|
|
EOF
|
|
)
|
|
# Send the JSON payload to the API via a POST request
|
|
curl -s -X 'POST' "$API_URL/releases" \
|
|
-H "Authorization: token $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$release_payload" > /dev/null
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Uses the Cargo CLI to publish the package to crates.io.
|
|
#
|
|
# Arguments:
|
|
# $1 - Package name
|
|
# ------------------------------------------------------------------------------
|
|
publish_to_crates_io() {
|
|
local pkg_name="$1"
|
|
|
|
echo " - Publishing $pkg_name to crates.io..."
|
|
|
|
# --allow-dirty is used because the CI environment might have modified files
|
|
# (like formatting lockfiles) before reaching this step.
|
|
cargo publish --token "$CRATES_TOKEN" -p "$pkg_name" --allow-dirty
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# The main workflow for a single package.
|
|
#
|
|
# Arguments:
|
|
# $1 - Package name
|
|
# $2 - Package version
|
|
# ------------------------------------------------------------------------------
|
|
process_package() {
|
|
local pkg_name="$1"
|
|
local pkg_version="$2"
|
|
local tag_name="${pkg_name}-v${pkg_version}"
|
|
|
|
echo "--- Checking $pkg_name ($pkg_version) ---"
|
|
|
|
if is_published_on_crates_io "$pkg_name" "$pkg_version"; then
|
|
echo " - $pkg_name v$pkg_version is already published. Skipping."
|
|
return 0
|
|
fi
|
|
|
|
echo " - New version detected. Proceeding with release..."
|
|
|
|
ensure_git_tag "$tag_name"
|
|
ensure_codeberg_release "$tag_name" "$pkg_name" "$pkg_version"
|
|
publish_to_crates_io "$pkg_name"
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Main Execution Block
|
|
# ==============================================================================
|
|
|
|
# Determine the correct build order
|
|
ORDERED_CRATES=$(get_ordered_crates)
|
|
|
|
# Get metadata for all packages we are allowed to publish
|
|
PACKAGES=$(get_publishable_packages "$ORDERED_CRATES")
|
|
|
|
# Exit early if there's nothing to do
|
|
if [ -z "$PACKAGES" ]; then
|
|
echo "No publishable packages found."
|
|
exit 0
|
|
fi
|
|
|
|
echo "Starting release process..."
|
|
|
|
# Loop through each package line by line and process it
|
|
echo "$PACKAGES" | while read -r PKG_NAME PKG_VERSION; do
|
|
# Skip empty lines
|
|
if [ -n "$PKG_NAME" ]; then
|
|
process_package "$PKG_NAME" "$PKG_VERSION"
|
|
fi
|
|
done
|
|
|
|
echo "--- All crates processed ---"
|