394 lines
13 KiB
YAML
394 lines
13 KiB
YAML
name: Release Plugin
|
||
run-name: "Release | ${{ inputs.name }} → ${{ inputs.tag }}"
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
payload:
|
||
description: 'Base64-kodierter JSON-Payload'
|
||
required: true
|
||
name:
|
||
description: 'Plugin Name'
|
||
required: true
|
||
tag:
|
||
description: 'Release Tag'
|
||
required: true
|
||
|
||
jobs:
|
||
release-plugin:
|
||
runs-on: alpine-latest
|
||
defaults:
|
||
run:
|
||
shell: bash
|
||
|
||
steps:
|
||
- name: Abhängigkeiten installieren
|
||
shell: sh
|
||
run: |
|
||
apk add --no-cache bash jq git rsync zip curl
|
||
|
||
- name: Daten zusammenstellen
|
||
id: daten
|
||
run: |
|
||
DECODED=$(echo "${{ github.event.inputs.payload }}" | base64 -d)
|
||
|
||
# Werte aus Payload auslesen
|
||
NAME=$(echo "$DECODED" | jq -r '.name')
|
||
GROUP=$(echo "$DECODED" | jq -r '.group')
|
||
VERSION=$(echo "$DECODED" | jq -r '.version')
|
||
CHANNEL=$(echo "$DECODED" | jq -r '.channel')
|
||
PRERELEASE=$(echo "$DECODED" | jq -r '.prerelease')
|
||
ZIP_FOLDER=$(echo "$DECODED" | jq -r '.zip_folder')
|
||
ZIP_FILE=$(echo "$DECODED" | jq -r '.zip_file')
|
||
TAG=$(echo "$DECODED" | jq -r '.tag')
|
||
|
||
# Outputs setzen
|
||
echo "name=$NAME" >> $GITHUB_OUTPUT
|
||
echo "group=$GROUP" >> $GITHUB_OUTPUT
|
||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||
echo "channel=$CHANNEL" >> $GITHUB_OUTPUT
|
||
echo "prerelease=$PRERELEASE" >> $GITHUB_OUTPUT
|
||
echo "zip_folder=$ZIP_FOLDER" >> $GITHUB_OUTPUT
|
||
echo "zip_file=$ZIP_FILE" >> $GITHUB_OUTPUT
|
||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||
|
||
# Debug-Ausgabe
|
||
echo "name=$NAME"
|
||
echo "group=$GROUP"
|
||
echo "version=$VERSION"
|
||
echo "channel=$CHANNEL"
|
||
echo "prerelease=$PRERELEASE"
|
||
echo "zip_folder=$ZIP_FOLDER"
|
||
echo "zip_file=$ZIP_FILE"
|
||
echo "tag=$TAG"
|
||
|
||
GIT_REPO_URL="https://${RELEASE_TOKEN}:x-oauth-basic@${{ vars.RELEASE_URL }}/${GITHUB_REPOSITORY}.git"
|
||
echo "git_repo_url=$GIT_REPO_URL" >> $GITHUB_OUTPUT
|
||
|
||
PAYLOAD_REPO="${GROUP}/${NAME}"
|
||
echo $PAYLOAD_REPO
|
||
GIT_PLUGIN_URL="https://${RELEASE_TOKEN}:x-oauth-basic@${{ vars.RELEASE_URL }}/$PAYLOAD_REPO.git"
|
||
echo "git_plugin_url=$GIT_PLUGIN_URL" >> $GITHUB_OUTPUT
|
||
|
||
- name: Repositorys klonen
|
||
run: |
|
||
git clone "$GIT_REPO_URL" repo
|
||
git clone "$GIT_PLUGIN_URL" plugin
|
||
cd plugin
|
||
git checkout "$CHANNEL"
|
||
cd ..
|
||
|
||
env:
|
||
CHANNEL: ${{ steps.daten.outputs.channel }}
|
||
GIT_REPO_URL: ${{ steps.daten.outputs.git_repo_url }}
|
||
GIT_PLUGIN_URL: ${{ steps.daten.outputs.git_plugin_url }}
|
||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||
|
||
- name: Metadata anpassen
|
||
run: |
|
||
cd plugin
|
||
|
||
sed -i "s/^version=.*/version=$VERSION-$CHANNEL/" "$FILE"
|
||
|
||
if [ "$PRERELEASE" = "true" ]; then
|
||
sed -i "s/^experimental=.*/experimental=true/" "$FILE"
|
||
else
|
||
sed -i "s/^experimental=.*/experimental=false/" "$FILE"
|
||
fi
|
||
|
||
# channel im repository ersetzen
|
||
sed -i "s|^\(repository=.*src/branch/\).*|\1$CHANNEL/|" "$FILE"
|
||
|
||
# Debug: Ausgabe der Datei
|
||
echo "== Inhalt der angepassten INI-Datei =="
|
||
cat "$FILE"
|
||
|
||
env:
|
||
FILE: "metadata.txt"
|
||
VERSION: ${{ steps.daten.outputs.version }}
|
||
PRERELEASE: ${{ steps.daten.outputs.prerelease }}
|
||
CHANNEL: ${{ steps.daten.outputs.channel }}
|
||
|
||
- name: ZIP-Datei erstellen
|
||
id: zip
|
||
run: |
|
||
mkdir -p ${ZIP_FOLDER}
|
||
|
||
rsync -a \
|
||
--exclude='.git' \
|
||
--exclude='.gitea' \
|
||
--exclude='.gitignore' \
|
||
--exclude='*/__pycache__/*' \
|
||
./plugin/ ./${ZIP_FOLDER}/
|
||
|
||
ls -la ${ZIP_FOLDER}/
|
||
zip -r "${ZIP_FILE}" "${ZIP_FOLDER}/"
|
||
ls -la
|
||
|
||
env:
|
||
ZIP_FOLDER: ${{ steps.daten.outputs.zip_folder }}
|
||
ZIP_FILE: ${{ steps.daten.outputs.zip_file }}
|
||
|
||
- name: Changelog einlesen
|
||
id: changelog
|
||
run: |
|
||
cd plugin
|
||
|
||
# Aktueller Block = alles vor dem ersten ---
|
||
CURRENT=$(awk '/^---/{exit} {print}' changelog.txt)
|
||
|
||
# Vollständige Historie = alles nach dem ersten ---
|
||
HISTORY=$(awk 'found{print} /^---/{found=1}' changelog.txt)
|
||
|
||
# Gitea Release Body zusammenbauen
|
||
VERSION="${{ steps.releaseinfo.outputs.version }}"
|
||
FULL=$(printf "## %s\n%s\n\n%s" "$VERSION" "$CURRENT" "$HISTORY")
|
||
|
||
echo "DEBUG | Aktueller Changelog:"
|
||
echo "$CURRENT"
|
||
|
||
# Für GITHUB_OUTPUT: Multiline via EOF-Marker
|
||
echo "current<<EOF" >> $GITHUB_OUTPUT
|
||
echo "$CURRENT" >> $GITHUB_OUTPUT
|
||
echo "EOF" >> $GITHUB_OUTPUT
|
||
|
||
echo "full<<EOF" >> $GITHUB_OUTPUT
|
||
echo "$FULL" >> $GITHUB_OUTPUT
|
||
echo "EOF" >> $GITHUB_OUTPUT
|
||
|
||
- name: Gitea-Release erstellen
|
||
id: create_release
|
||
run: |
|
||
API_URL="https://${{ vars.RELEASE_URL }}/api/v1/repos/${PLUGIN_GROUP}/${PLUGIN_NAME}/releases"
|
||
|
||
JSON=$(jq -n \
|
||
--arg tag "$VERSION-$CHANNEL" \
|
||
--arg name "Version $VERSION-$CHANNEL" \
|
||
--arg body "$BODY" \
|
||
--argjson prerelease "$PRERELEASE" \
|
||
'{tag_name: $tag, name: $name, body: $body, prerelease: $prerelease}')
|
||
|
||
API_RESPONSE=$(curl -s -X POST "$API_URL" \
|
||
-H "accept: application/json" \
|
||
-H "Authorization: token $RELEASE_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d "$JSON")
|
||
|
||
RELEASE_ID=$(echo "$API_RESPONSE" | jq -r '.id')
|
||
|
||
if [ "$RELEASE_ID" = "null" ] || [ -z "$RELEASE_ID" ]; then
|
||
echo "Fehler beim Erstellen des Releases!"
|
||
echo "$API_RESPONSE"
|
||
exit 1
|
||
fi
|
||
|
||
echo "release_id=$RELEASE_ID" >> $GITHUB_OUTPUT
|
||
env:
|
||
PRERELEASE: ${{ steps.daten.outputs.prerelease }}
|
||
BODY: ${{ steps.changelog.outputs.current }}
|
||
VERSION: ${{ steps.daten.outputs.version }}
|
||
TAG: ${{ steps.daten.outputs.tag }}
|
||
PLUGIN_NAME: ${{ steps.daten.outputs.name }}
|
||
PLUGIN_GROUP: ${{ steps.daten.outputs.group }}
|
||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||
CHANNEL: ${{ steps.daten.outputs.channel }}
|
||
|
||
- name: ZIP-Datei hochladen
|
||
run: |
|
||
pwd
|
||
ls -la
|
||
echo @${ZIP_FILE}
|
||
|
||
API_URL="https://${{ vars.RELEASE_URL }}/api/v1/repos/${PLUGIN_GROUP}/${PLUGIN_NAME}/releases/${RELEASE_ID}/assets?name=${ZIP_FILE}"
|
||
|
||
curl -sf -X POST "$API_URL" \
|
||
-H "Authorization: token $RELEASE_TOKEN" \
|
||
-H "Content-Type: application/zip" \
|
||
--data-binary "@${ZIP_FILE}" \
|
||
-o upload_response.json
|
||
|
||
if jq -e '.id' upload_response.json >/dev/null 2>&1; then
|
||
echo "ZIP erfolgreich hochgeladen."
|
||
else
|
||
echo "Fehler beim Hochladen der ZIP!"
|
||
cat upload_response.json
|
||
exit 1
|
||
fi
|
||
|
||
env:
|
||
RELEASE_ID: ${{ steps.create_release.outputs.release_id }}
|
||
ZIP_FILE: ${{ steps.daten.outputs.zip_file }}
|
||
PLUGIN_NAME: ${{ steps.daten.outputs.name }}
|
||
PLUGIN_GROUP: ${{ steps.daten.outputs.group }}
|
||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||
|
||
- name: Changelog aktualisieren
|
||
run: |
|
||
cd plugin
|
||
TMP_FILE=$(mktemp)
|
||
|
||
{
|
||
echo "---"
|
||
echo "Version $VERSION-$CHANNEL:"
|
||
cat "$FILE"
|
||
} > "$TMP_FILE"
|
||
|
||
mv "$TMP_FILE" "$FILE"
|
||
|
||
# Debug
|
||
echo "== Neuer Inhalt von changelog.txt =="
|
||
head -n 5 "$FILE"
|
||
|
||
cd ~
|
||
pwd
|
||
env:
|
||
FILE: "changelog.txt"
|
||
VERSION: ${{ steps.daten.outputs.version }}
|
||
CHANNEL: ${{ steps.daten.outputs.channel }}
|
||
|
||
- name: Repository aktualisieren
|
||
run: |
|
||
cd plugin
|
||
|
||
git config user.name "release-bot"
|
||
git config user.email "ci@example.local"
|
||
|
||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||
echo "Lösche alten lokalen Tag $TAG"
|
||
git tag -d "$TAG"
|
||
echo "Lösche alten Remote-Tag $TAG"
|
||
git -c http.extraheader="AUTHORIZATION: bearer $RELEASE_TOKEN" push origin :refs/tags/"$TAG"
|
||
else
|
||
echo "Tag $TAG nicht vorhanden"
|
||
fi
|
||
|
||
git add metadata.txt changelog.txt
|
||
git commit -m "Release $VERSION-$CHANNEL"
|
||
|
||
git -c http.extraheader="AUTHORIZATION: bearer $RELEASE_TOKEN" push origin HEAD:"$CHANNEL"
|
||
|
||
|
||
env:
|
||
CHANNEL: ${{ steps.daten.outputs.channel }}
|
||
VERSION: ${{ steps.daten.outputs.version }}
|
||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||
TAG: ${{ steps.daten.outputs.tag }}
|
||
|
||
- name: XML-Datei bestimmen
|
||
id: xmlfile
|
||
run: |
|
||
case "${{ steps.daten.outputs.channel }}" in
|
||
stable) FILE="plugins.xml" ;;
|
||
testing) FILE="plugins-testing.xml" ;;
|
||
unstable) FILE="plugins-unstable.xml" ;;
|
||
esac
|
||
echo "file=$FILE" >> $GITHUB_OUTPUT
|
||
|
||
- name: XML-Datei initialisieren
|
||
run: |
|
||
cd repo
|
||
FILE="${{ steps.xmlfile.outputs.file }}"
|
||
if [ ! -s "$FILE" ]; then
|
||
echo "<plugins></plugins>" > "$FILE"
|
||
fi
|
||
|
||
- name: Alten Plugin-Eintrag entfernen
|
||
run: |
|
||
cd repo
|
||
FILE="${{ steps.xmlfile.outputs.file }}"
|
||
ID="${{ steps.payload.outputs.id }}"
|
||
|
||
# Entfernt den kompletten Plugin-Block
|
||
sed -i "/<pyqgis_plugin[^>]*plugin_id=\"${ID//\//\\/}\"/,/<\/pyqgis_plugin>/d" "$FILE"
|
||
|
||
- name: metadata.txt einlesen
|
||
id: metadata
|
||
run: |
|
||
cd plugin
|
||
while read -r line || [ -n "$line" ]; do
|
||
key="${line%%=*}"
|
||
value="${line#*=}"
|
||
echo "$key=$value" >> $GITHUB_OUTPUT
|
||
echo "$key=$value"
|
||
done < $FILE
|
||
env:
|
||
FILE: "metadata.txt"
|
||
|
||
- name: Template anwenden und neue XML erzeugen
|
||
run: |
|
||
cd repo
|
||
|
||
FILE="${{ steps.xmlfile.outputs.file }}"
|
||
|
||
git fetch origin hidden/templates
|
||
git checkout origin/hidden/templates -- plugin.template
|
||
|
||
TEMPLATE="plugin.template"
|
||
cat "$TEMPLATE"
|
||
|
||
# Template laden
|
||
ENTRY=$(cat "$TEMPLATE")
|
||
|
||
ENTRY="${ENTRY//\{\{NAME\}\}/${{ steps.metadata.outputs.name }}}"
|
||
ENTRY="${ENTRY//\{\{QGIS_MIN\}\}/${{ steps.metadata.outputs.qgisMinimumVersion }}}"
|
||
ENTRY="${ENTRY//\{\{QGIS_MAX\}\}/${{ steps.metadata.outputs.qgisMaximumVersion }}}"
|
||
ENTRY="${ENTRY//\{\{DESCRIPTION\}\}/${{ steps.metadata.outputs.description }}}"
|
||
ENTRY="${ENTRY//\{\{VERSION\}\}/${{ steps.metadata.outputs.version }}}"
|
||
ENTRY="${ENTRY//\{\{AUTHOR\}\}/${{ steps.metadata.outputs.author }}}"
|
||
ENTRY="${ENTRY//\{\{EMAIL\}\}/${{ steps.metadata.outputs.email }}}"
|
||
ENTRY="${ENTRY//\{\{HOMEPAGE\}\}/${{ steps.metadata.outputs.homepage }}}"
|
||
ENTRY="${ENTRY//\{\{TRACKER\}\}/${{ steps.metadata.outputs.tracker }}}"
|
||
ENTRY="${ENTRY//\{\{REPOSITORY\}\}/${{ steps.metadata.outputs.repository }}}"
|
||
ENTRY="${ENTRY//\{\{EXPERIMENTAL\}\}/${{ steps.metadata.outputs.experimental }}}"
|
||
ENTRY="${ENTRY//\{\{DEPRECATED\}\}/${{ steps.metadata.outputs.deprecated }}}"
|
||
|
||
ENTRY="${ENTRY//\{\{ID\}\}/${{ steps.daten.outputs.zip_folder }}}"
|
||
|
||
URL=${{ steps.metadata.outputs.homepage }}/releases/download/${{ steps.daten.outputs.version }}-${{ steps.daten.outputs.channel }}/${{ steps.daten.outputs.zip_file }}
|
||
ENTRY="${ENTRY//\{\{URL\}\}/$URL}"
|
||
|
||
CHANGELOG_RAW="${{ steps.changelog.outputs.current }}"
|
||
CHANGELOG_ESCAPED="${CHANGELOG_RAW//$'\n'/ }"
|
||
CHANGELOG_ESCAPED=$(printf '%s' "$CHANGELOG_ESCAPED" | sed -e 's/[\/&|]/\\&/g')
|
||
ENTRY=$(printf '%s' "$ENTRY" | sed "s/{{CHANGELOG}}/$CHANGELOG_ESCAPED/g")
|
||
|
||
echo "$ENTRY"
|
||
|
||
# Neue Datei erzeugen
|
||
{
|
||
# Alles vor </plugins>
|
||
sed '/<\/plugins>/d' "$FILE"
|
||
|
||
# Neuen Eintrag einfügen
|
||
printf "%s\n" "$ENTRY"
|
||
|
||
# </plugins> wieder anhängen
|
||
echo "</plugins>"
|
||
} > new.xml
|
||
|
||
mv new.xml "$FILE"
|
||
rm $TEMPLATE
|
||
|
||
- name: Commit & Push
|
||
run: |
|
||
cd repo
|
||
|
||
git config user.name "release-bot"
|
||
git config user.email "ci@example.local"
|
||
|
||
git add .
|
||
|
||
# Commit nur, wenn Änderungen vorhanden sind
|
||
if ! git diff --cached --quiet; then
|
||
git commit -m "${{ inputs.name }} ${{ steps.metadata.outputs.version }}"
|
||
else
|
||
echo "Keine Änderungen – kein Commit notwendig."
|
||
exit 0
|
||
fi
|
||
|
||
# Token in die URL einbauen
|
||
git remote set-url origin "https://${{ secrets.RELEASE_TOKEN }}:@${{ vars.RELEASE_URL }}/AG_QGIS/Repository.git"
|
||
|
||
git push origin main
|
||
|