Files
GitHubToGiTea/.woodpecker.yml

193 lines
9.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# .woodpecker.yml
trigger:
# Запускать каждый час (или как вам нужно)
cron:
- 'sync-hourly@0 * * * *' # Имя крона@расписание
pipeline:
sync_releases:
image: alpine/git # Базовый образ с git
secrets: [ gitea_url, gitea_token, github_token ] # Подключаем секреты
environment:
# Передаем секреты и имя файла в окружение контейнера
GITEA_URL: ${GITEA_URL}
GITEA_TOKEN: ${GITEA_TOKEN}
GITHUB_TOKEN: ${GITHUB_TOKEN} # Может быть пустым, если не используется
REPO_LIST_FILE: repos_to_sync.txt # Имя файла со списком репозиториев
commands:
# 1. Установка зависимостей (curl и jq)
- apk update && apk add curl jq bash
# 2. Запуск скрипта синхронизации
- |
#!/bin/bash
set -e # Останавливаться при ошибках
# set -x # Для отладки можно раскомментировать
echo "Starting release sync..."
# --- Конфигурация ---
REPO_FILE="${REPO_LIST_FILE:-repos_to_sync.txt}" # Используем переменную окружения или дефолтное имя
# Проверка наличия файла репозиториев
if [ ! -f "$REPO_FILE" ]; then
echo "Error: Repository list file '$REPO_FILE' not found!"
exit 1
fi
# Проверка наличия GITEA_TOKEN
if [ -z "$GITEA_TOKEN" ]; then
echo "Error: GITEA_TOKEN secret is not set!"
exit 1
fi
# Заголовок авторизации для Gitea
GITEA_AUTH_HEADER="Authorization: token ${GITEA_TOKEN}"
GITEA_API_URL="${GITEA_URL}/api/v1"
# Заголовок авторизации для GitHub (если токен есть)
GITHUB_AUTH_HEADER=""
if [ -n "$GITHUB_TOKEN" ]; then
GITHUB_AUTH_HEADER="Authorization: token ${GITHUB_TOKEN}"
fi
GITHUB_API_URL="https://api.github.com"
# --- Вспомогательные функции (без изменений) ---
download_asset() {
local url="$1"
local filename="$2"
echo "Downloading asset: $filename from $url"
curl -L -H "$GITHUB_AUTH_HEADER" -o "$filename" "$url"
if [ $? -ne 0 ]; then
echo "Error downloading asset: $filename"
return 1
fi
return 0
}
upload_asset() {
local gitea_repo_path="$1"
local release_id="$2"
local filename="$3"
echo "Uploading asset: $filename to Gitea release ID $release_id"
UPLOAD_URL="${GITEA_API_URL}/repos/${gitea_repo_path}/releases/${release_id}/assets?name=$(basename "$filename")"
# Используем --fail для curl, чтобы он возвращал ненулевой код при HTTP ошибках > 400
curl -sf --fail -X POST -H "$GITEA_AUTH_HEADER" -H "Content-Type: application/octet-stream" --data-binary "@$filename" "$UPLOAD_URL"
if [ $? -ne 0 ]; then
echo "Error uploading asset: $filename"
# Оставляем файл для возможного анализа при ошибке
return 1
else
rm "$filename" # Удаляем локальный файл после успешной загрузки
return 0
fi
}
# --- Основной цикл по репозиториям из файла ---
echo "Reading repository list from $REPO_FILE"
while IFS= read -r repo_pair || [[ -n "$repo_pair" ]]; do # Читаем строки из файла
# Пропускаем пустые строки и комментарии
if [[ -z "$repo_pair" || "$repo_pair" == \#* ]]; then
continue
fi
# Проверяем формат строки
if ! echo "$repo_pair" | grep -q ':'; then
echo "Warning: Skipping invalid line in $REPO_FILE: $repo_pair (format should be github/repo:gitea/repo)"
continue
fi
GITHUB_REPO_PATH=$(echo "$repo_pair" | cut -d':' -f1)
GITEA_REPO_PATH=$(echo "$repo_pair" | cut -d':' -f2)
echo "-------------------------------------"
echo "Syncing releases for $GITHUB_REPO_PATH -> $GITEA_REPO_PATH"
# 1. Получаем существующие теги релизов из Gitea
echo "Fetching existing Gitea releases for $GITEA_REPO_PATH..."
# Используем --fail, чтобы прервать пайплайн, если Gitea недоступен или репо нет
GITEA_RELEASES_JSON=$(curl -sf --fail -H "$GITEA_AUTH_HEADER" "${GITEA_API_URL}/repos/${GITEA_REPO_PATH}/releases") || \
{ echo "Error fetching Gitea releases for $GITEA_REPO_PATH, stopping sync."; exit 1; }
EXISTING_GITEA_TAGS=$(echo "$GITEA_RELEASES_JSON" | jq -r '.[].tag_name')
# echo "Found Gitea tags: $EXISTING_GITEA_TAGS" # Можно включить для отладки
# 2. Получаем последние релизы из GitHub (например, 20 последних для большей надежности)
echo "Fetching latest GitHub releases for $GITHUB_REPO_PATH..."
# Используем --fail для обработки ошибок GitHub API
GITHUB_RELEASES_JSON=$(curl -sf --fail -H "$GITHUB_AUTH_HEADER" "${GITHUB_API_URL}/repos/${GITHUB_REPO_PATH}/releases?per_page=20") || \
{ echo "Error fetching GitHub releases for $GITHUB_REPO_PATH, skipping this repo."; continue; } # Пропускаем репо при ошибке GitHub
# 3. Итерируем по релизам GitHub в ОБРАТНОМ порядке
echo "$GITHUB_RELEASES_JSON" | jq -c '.[] | select(.draft == false)' | tac | while IFS= read -r release_json; do
TAG_NAME=$(echo "$release_json" | jq -r '.tag_name')
# Проверяем, есть ли уже релиз с таким тегом в Gitea
if echo "$EXISTING_GITEA_TAGS" | grep -q -x -F "$TAG_NAME"; then # -x: точное совпадение строки, -F: строка, а не регэкс
# echo "Release tag $TAG_NAME already exists in Gitea, skipping."
continue # Переходим к следующему релизу GitHub
fi
echo ">>> Found new release tag in GitHub: $TAG_NAME. Processing..."
# Извлекаем данные релиза
RELEASE_NAME=$(echo "$release_json" | jq -r '.name')
RELEASE_BODY=$(echo "$release_json" | jq -r '.body // ""')
IS_PRERELEASE=$(echo "$release_json" | jq -r '.prerelease')
ASSETS=$(echo "$release_json" | jq -c '.assets[]')
# 4. Создаем релиз в Gitea
echo "Creating release $RELEASE_NAME (tag: $TAG_NAME) in Gitea..."
CREATE_PAYLOAD=$(jq -n --arg tag "$TAG_NAME" --arg name "$RELEASE_NAME" --arg body "$RELEASE_BODY" --argjson prerelease "$IS_PRERELEASE" \
'{tag_name: $tag, name: $name, body: $body, prerelease: $prerelease}')
# Используем --fail для обработки ошибок создания релиза (например, нет тега)
GITEA_NEW_RELEASE_JSON=$(curl -sf --fail -X POST -H "$GITEA_AUTH_HEADER" -H "Content-Type: application/json" \
-d "$CREATE_PAYLOAD" \
"${GITEA_API_URL}/repos/${GITEA_REPO_PATH}/releases")
if [ $? -ne 0 ]; then
echo "Error creating release $TAG_NAME in Gitea. Maybe the tag '$TAG_NAME' is not synced yet or another issue occurred. Skipping this release."
continue # Пропускаем этот релиз, попробуем в следующий раз
fi
GITEA_RELEASE_ID=$(echo "$GITEA_NEW_RELEASE_JSON" | jq -r '.id')
echo "Gitea release created with ID: $GITEA_RELEASE_ID"
# 5. Скачиваем и загружаем ассеты
UPLOAD_FAILED_COUNT=0
if [ -n "$ASSETS" ]; then
echo "$ASSETS" | while IFS= read -r asset_json; do
ASSET_NAME=$(echo "$asset_json" | jq -r '.name')
ASSET_URL=$(echo "$asset_json" | jq -r '.browser_download_url')
TMP_ASSET_FILE="asset_${ASSET_NAME}" # Временное имя файла
if download_asset "$ASSET_URL" "$TMP_ASSET_FILE"; then
if ! upload_asset "$GITEA_REPO_PATH" "$GITEA_RELEASE_ID" "$TMP_ASSET_FILE"; then
((UPLOAD_FAILED_COUNT++))
# Оставляем временный файл при ошибке загрузки для анализа
fi
else
echo "Skipping asset $ASSET_NAME due to download error."
((UPLOAD_FAILED_COUNT++))
fi
done
else
echo "No assets found for release $TAG_NAME."
fi
if [ $UPLOAD_FAILED_COUNT -eq 0 ]; then
echo "Successfully processed release $TAG_NAME with all assets."
else
echo "Processed release $TAG_NAME, but $UPLOAD_FAILED_COUNT asset(s) failed to download or upload."
fi
done # Конец цикла по релизам GitHub
echo "Finished sync for $GITHUB_REPO_PATH -> $GITEA_REPO_PATH"
echo "-------------------------------------"
done < "$REPO_FILE" # Перенаправляем файл в цикл while
echo "Release sync finished."