diff --git a/.gitea/workflows/deployProduction.yml b/.gitea/workflows/deployProduction.yml index 92a41db..9412cc5 100644 --- a/.gitea/workflows/deployProduction.yml +++ b/.gitea/workflows/deployProduction.yml @@ -1,32 +1,176 @@ -name: Deploy Production +name: Update WebHosting on: push: branches: [main] - workflow_dispatch: jobs: - deploy: - runs-on: berufsbildung-latest + update: + runs-on: ubuntu-latest + env: + PACKAGES_FILE: .gitea/production-packages.txt + VERSIONS_FILE: ${{ github.workspace }}/resolved-versions.tsv + PACKAGE_OWNER: bb_if_produktiv + steps: - - name: Clean workspace - run: | - find "${GITHUB_WORKSPACE:?}" -mindepth 1 -maxdepth 1 -exec rm -rf {} + - - - name: Login to registry - run: | - echo "${{ secrets.REGISTRY_TOKEN }}" | docker login gitea.psi.ch \ - -u "bb_if_produktiv" \ - --password-stdin - - name: Checkout uses: actions/checkout@v3 - - name: Pull images - run: docker compose pull - - - name: Restart services + - name: Resolve latest package versions + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | - docker compose down - docker compose build --no-cache - docker compose up -d --force-recreate + set -euo pipefail + + fetch_latest() { + local name="$1" + local page=1 + local items='[]' + local resp count latest + + while true; do + resp="$( + curl -fsS \ + -H "Authorization: token ${GITEA_TOKEN}" \ + "https://gitea.psi.ch/api/v1/packages/${PACKAGE_OWNER}?type=container&q=${name}&limit=50&page=${page}" + )" + + items="$(printf '%s\n%s\n' "$items" "$resp" | jq -cs '.[0] + .[1]')" + count="$(jq 'length' <<<"$resp")" + if [ "$count" -lt 50 ]; then + break + fi + page=$((page + 1)) + done + + latest="$( + jq -r --arg name "$name" ' + map(select( + .name == $name + and (.version | test("^(latest|dev|main)$") | not) + )) + | sort_by(.created_at) + | last + | .version // empty + ' <<<"$items" + )" + + if [ -z "$latest" ]; then + echo "No usable container version found for ${name}" >&2 + exit 1 + fi + + printf '%s\n' "$latest" + } + + : > "$VERSIONS_FILE" + found=0 + + while read -r package image; do + case "$package" in + ''|'#'*) continue ;; + esac + + image="${image:-${PACKAGE_OWNER}/${package}}" + version="$(fetch_latest "$package")" + printf '%s\t%s\t%s\n' "$package" "$image" "$version" >> "$VERSIONS_FILE" + echo "${package}=${version} (${image})" + found=1 + done < "$PACKAGES_FILE" + + if [ "$found" -eq 0 ]; then + echo "No packages listed in ${PACKAGES_FILE}" >&2 + exit 1 + fi + + - name: Create fork + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + set -euo pipefail + status="$( + curl -sS -o /tmp/fork.json -w "%{http_code}" -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + https://gitea.psi.ch/api/v1/repos/linux/WebHosting_DMZ/forks \ + -d '{}' + )" + if [ "$status" != "201" ] && [ "$status" != "202" ] && [ "$status" != "409" ]; then + echo "Fork request failed with HTTP ${status}" + cat /tmp/fork.json + exit 1 + fi + + - name: Clone fork + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + git clone \ + https://oauth2:${GITEA_TOKEN}@gitea.psi.ch/${{ github.repository_owner }}/WebHosting_DMZ.git \ + webhosting + + - name: Change versions + id: change + run: | + set -euo pipefail + + while IFS=$'\t' read -r package image version; do + if ! grep -qE "${image}:[^[:space:]]+" webhosting/docker-compose.yaml; then + echo "Image ${image} not found in docker-compose.yaml (package ${package})" >&2 + exit 1 + fi + + sed -i \ + "s#${image}:[^[:space:]]*#${image}:${version}#g" \ + webhosting/docker-compose.yaml + done < "$VERSIONS_FILE" + + if git -C webhosting diff --quiet docker-compose.yaml; then + echo "Compose already at latest package versions; skipping PR." + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Commit and push + if: steps.change.outputs.changed == 'true' + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + set -euo pipefail + cd webhosting + + BRANCH="update-versions-${{ github.run_number }}" + + git checkout -b "$BRANCH" + + git config user.name "Gitea Actions" + git config user.email "actions@localhost" + + git add docker-compose.yaml + git commit -m "Update package versions" + + git push origin "$BRANCH" + + - name: Create Pull Request + if: steps.change.outputs.changed == 'true' + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + set -euo pipefail + + body="$( + awk -F '\t' '{ printf "- `%s` (%s): `%s`\n", $1, $2, $3 }' "$VERSIONS_FILE" + )" + + jq -n \ + --arg title "Update package versions" \ + --arg body "Automated version update:"$'\n\n'"${body}" \ + --arg head "${{ github.repository_owner }}:update-versions-${{ github.run_number }}" \ + --arg base "main" \ + '{title: $title, body: $body, head: $head, base: $base}' \ + | curl -fsS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d @- \ + https://gitea.psi.ch/api/v1/repos/linux/WebHosting_DMZ/pulls