diff --git a/.github/workflows/ccs-update.yaml b/.github/workflows/ccs-update.yaml deleted file mode 100644 index b36cd80a..00000000 --- a/.github/workflows/ccs-update.yaml +++ /dev/null @@ -1,85 +0,0 @@ -name: Check CounterStrikeSharp Release - -on: - workflow_dispatch: - description: 'Manually trigger CounterStrikeSharp update check' - -jobs: - check-url: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v7 - - - name: Extract current URL from Dockerfile - run: | - CURRENT_URL=$(grep 'ENV COUNTER_STRIKE_SHARP_URL' apps/counterstrikesharp/Dockerfile | cut -d'=' -f2) - echo "CURRENT_URL=$CURRENT_URL" >> $GITHUB_ENV - - - name: Check latest release URL - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - RESPONSE=$(curl -sSL \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GH_TOKEN" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/roflmuffin/CounterStrikeSharp/releases/latest) - if ! echo "$RESPONSE" | jq -e '.assets' > /dev/null; then - echo "Unexpected API response:" - echo "$RESPONSE" - exit 1 - fi - LATEST_URL=$(echo "$RESPONSE" | jq -r '.assets[] | select(.name | contains("linux") and contains("runtime")) | .browser_download_url') - if [ -z "$LATEST_URL" ]; then - echo "No matching asset found in latest release" - echo "$RESPONSE" | jq -r '.assets[].name' - exit 1 - fi - echo "LATEST_URL=$LATEST_URL" >> $GITHUB_ENV - - - name: Compare URLs - if: env.CURRENT_URL != env.LATEST_URL - run: | - echo "URL has changed!" - echo "Current URL: ${{ env.CURRENT_URL }}" - echo "Latest URL: ${{ env.LATEST_URL }}" - - # The runtime and EVERY plugin's nuget must move together or the ABI - # breaks. The csproj list is discovered rather than written down: this - # step used to name apps/counterstrikesharp alone, so when the practice - # plugin arrived with its own pin it silently stayed a version behind - # the runtime it gets loaded into. - - name: Update Dockerfile / csprojs - if: env.CURRENT_URL != env.LATEST_URL - run: | - set -euo pipefail - VERSION_NUMBER=$(echo ${{ env.LATEST_URL }} | grep -oP 'v\K\d+\.\d+\.\d+') - - sed -i 's|ENV COUNTER_STRIKE_SHARP_URL=.*|ENV COUNTER_STRIKE_SHARP_URL=${{ env.LATEST_URL }}|' apps/counterstrikesharp/Dockerfile - grep -q 'ENV COUNTER_STRIKE_SHARP_URL=' apps/counterstrikesharp/Dockerfile \ - || { echo "::error::could not set COUNTER_STRIKE_SHARP_URL in apps/counterstrikesharp/Dockerfile"; exit 1; } - - git config user.name github-actions - git config user.email github-actions@github.com - git add apps/counterstrikesharp/Dockerfile - - # `|| true` because grep exits 1 when it matches nothing, and - # `set -e` would abort the step before the friendly error below -- - # which is the whole reason that branch exists. - CSPROJS=$(grep -rl 'Include="CounterStrikeSharp.API"' --include='*.csproj' apps || true) - if [ -z "$CSPROJS" ]; then - echo "::error::no csproj references CounterStrikeSharp.API -- the pin pattern must have changed" - exit 1 - fi - - for csproj in $CSPROJS; do - sed -i "s|> "$RUNNER_TEMP/images" + echo "SwiftlyS2 to ${LATEST}" >> "$RUNNER_TEMP/bumps" + + - name: CounterStrikeSharp + if: ${{ !cancelled() }} + run: | + set -euo pipefail + git checkout -- . + CURRENT_URL=$(grep -oP 'ENV COUNTER_STRIKE_SHARP_URL=\K\S+' apps/counterstrikesharp/Dockerfile) + LATEST_URL=$(gh api repos/roflmuffin/CounterStrikeSharp/releases/latest \ + --jq '[.assets[] | select(.name | contains("linux") and contains("runtime")) | .browser_download_url] | first // ""') + echo "current=$CURRENT_URL latest=$LATEST_URL" + + if [ -z "$LATEST_URL" ]; then + echo "::error::no linux runtime asset in the latest CounterStrikeSharp release" + exit 1 + fi + if [ "$CURRENT_URL" = "$LATEST_URL" ]; then + exit 0 + fi + VERSION_NUMBER=$(echo "$LATEST_URL" | grep -oP 'v\K\d+\.\d+\.\d+' | head -1) + + sed -i "s|ENV COUNTER_STRIKE_SHARP_URL=.*|ENV COUNTER_STRIKE_SHARP_URL=${LATEST_URL}|" apps/counterstrikesharp/Dockerfile + grep -qF "ENV COUNTER_STRIKE_SHARP_URL=${LATEST_URL}" apps/counterstrikesharp/Dockerfile \ + || { echo "::error::could not set COUNTER_STRIKE_SHARP_URL in apps/counterstrikesharp/Dockerfile"; exit 1; } + + mapfile -t CSPROJS < <(grep -rl 'Include="CounterStrikeSharp.API"' --include='*.csproj' apps || true) + if [ ${#CSPROJS[@]} -eq 0 ]; then + echo "::error::no csproj references CounterStrikeSharp.API -- the pin pattern must have changed" + exit 1 + fi + for csproj in "${CSPROJS[@]}"; do + sed -i "s|> "$RUNNER_TEMP/images" + echo "CounterStrikeSharp to v${VERSION_NUMBER}" >> "$RUNNER_TEMP/bumps" + + - name: Metamod + if: ${{ !cancelled() }} + run: | + set -euo pipefail + git checkout -- . + CURRENT_URL=$(grep -oP 'ENV METAMOD_URL=\K\S+' apps/counterstrikesharp/Dockerfile) + # not every release ships a linux tarball, so take the newest one that does + LATEST_URL=$(gh api "repos/alliedmodders/metamod-source/releases?per_page=20" \ + --jq '[.[] | select(.tag_name | startswith("2.")) | .assets[] | select(.name | test("^mmsource-.*-linux\\.tar\\.gz$")) | .browser_download_url] | first // ""') + echo "current=$CURRENT_URL latest=$LATEST_URL" + + if [ -z "$LATEST_URL" ]; then + echo "::error::no linux release asset found for metamod-source 2.x" + exit 1 + fi + if [ "$CURRENT_URL" = "$LATEST_URL" ]; then + exit 0 + fi + BUILD_ID=$(echo "$LATEST_URL" | grep -oP '(?<=mmsource-)[^/]+(?=-linux)') + + sed -i "s|ENV METAMOD_URL=.*|ENV METAMOD_URL=${LATEST_URL}|" apps/counterstrikesharp/Dockerfile + grep -qF "ENV METAMOD_URL=${LATEST_URL}" apps/counterstrikesharp/Dockerfile \ + || { echo "::error::could not set METAMOD_URL in apps/counterstrikesharp/Dockerfile"; exit 1; } + + git add apps/counterstrikesharp/Dockerfile + printf 'css\nvalidator\n' >> "$RUNNER_TEMP/images" + echo "Metamod to ${BUILD_ID}" >> "$RUNNER_TEMP/bumps" + + - name: AddonsManager + if: ${{ !cancelled() }} + run: | + set -euo pipefail + git checkout -- . + CURRENT=$(grep -oP 'ADDONS_MANAGER_VERSION="\K[^"]+' apps/swiftly/Dockerfile) + RELEASE=$(gh api repos/SwiftlyS2-Plugins/AddonsManager/releases/latest) + LATEST=$(jq -r .tag_name <<<"$RELEASE") + echo "current=$CURRENT latest=$LATEST" + + if [ -z "$LATEST" ] || [ "$LATEST" = "null" ] || [ "$CURRENT" = "$LATEST" ]; then + exit 0 + fi + + # The download URL is built from the version, and the asset has been + # renamed before (AddonsManager.zip became AddonsManager-v2.0.4.zip), + # so a version-only bump would bake an image whose download 404s. + ASSET="AddonsManager-${LATEST}.zip" + if ! jq -e --arg name "$ASSET" 'any(.assets[]; .name == $name)' <<<"$RELEASE" > /dev/null; then + echo "::error::AddonsManager ${LATEST} ships no ${ASSET} ($(jq -r '[.assets[].name] | join(", ")' <<<"$RELEASE")); update ADDONS_MANAGER_URL in apps/swiftly/Dockerfile by hand" + exit 1 + fi + + sed -i "s|ADDONS_MANAGER_VERSION=\"[^\"]*\"|ADDONS_MANAGER_VERSION=\"${LATEST}\"|" apps/swiftly/Dockerfile + grep -q "ADDONS_MANAGER_VERSION=\"${LATEST}\"" apps/swiftly/Dockerfile \ + || { echo "::error::could not set ADDONS_MANAGER_VERSION in apps/swiftly/Dockerfile"; exit 1; } + + git add apps/swiftly/Dockerfile + echo sw >> "$RUNNER_TEMP/images" + echo "AddonsManager to ${LATEST}" >> "$RUNNER_TEMP/bumps" + + - name: Commit and rebuild + if: ${{ !cancelled() }} + run: | + set -euo pipefail + git checkout -- . + if [ ! -s "$RUNNER_TEMP/bumps" ]; then + echo "everything is current" + exit 0 + fi + + git config user.name github-actions + git config user.email github-actions@github.com + git commit -m "chore: update $(paste -sd ';' "$RUNNER_TEMP/bumps" | sed 's/;/, /g')" + git pull --rebase --quiet + git push + + # A push made with GITHUB_TOKEN starts no workflows, so CI never sees + # this commit on its own and the image keeps the old version until + # something unrelated lands. workflow_dispatch is the one event that + # token is allowed to start. + IMAGES=$(sort -u "$RUNNER_TEMP/images" | paste -sd, -) + gh workflow run ci.yaml --ref "$GITHUB_REF_NAME" -f only="$IMAGES" + echo "dispatched CI for $IMAGES" diff --git a/.github/workflows/metamod-update.yaml b/.github/workflows/metamod-update.yaml deleted file mode 100644 index c5fe33e2..00000000 --- a/.github/workflows/metamod-update.yaml +++ /dev/null @@ -1,47 +0,0 @@ -name: Check MetaMod Source Release - -on: - workflow_dispatch: - description: 'Manually trigger MetaMod Source update check' - -jobs: - check-url: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v7 - - - name: Extract current URL from Dockerfile - run: | - CURRENT_URL=$(grep 'ENV METAMOD_URL' apps/counterstrikesharp/Dockerfile | cut -d'=' -f2) - echo "CURRENT_URL=$CURRENT_URL" >> $GITHUB_ENV - - - name: Check latest release URL - run: | - # not every release ships a linux tarball, so take the newest one that does - LATEST_URL=$(curl -sf -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ - "https://api.github.com/repos/alliedmodders/metamod-source/releases?per_page=20" \ - | jq -r '[.[] | select(.tag_name | startswith("2.")) | .assets[] | select(.name | test("^mmsource-.*-linux\\.tar\\.gz$")) | .browser_download_url] | first // ""') - if [ -z "$LATEST_URL" ]; then - echo "::error::No linux release asset found for metamod-source 2.x" - exit 1 - fi - echo "LATEST_URL=$LATEST_URL" >> $GITHUB_ENV - - - name: Compare URLs - if: env.CURRENT_URL != env.LATEST_URL - run: | - echo "URL has changed!" - echo "Current URL: ${{ env.CURRENT_URL }}" - echo "Latest URL: ${{ env.LATEST_URL }}" - - - name: Update Dockerfile (optional) - if: env.CURRENT_URL != env.LATEST_URL - run: | - sed -i "s|ENV METAMOD_URL=.*|ENV METAMOD_URL=${LATEST_URL}|" apps/counterstrikesharp/Dockerfile - git config user.name github-actions - git config user.email github-actions@github.com - git add apps/counterstrikesharp/Dockerfile - BUILD_ID=$(echo "$LATEST_URL" | grep -oP '(?<=mmsource-)[^/]+(?=-linux)') - git commit -m "chore: update metamod to version ${BUILD_ID}" - git push diff --git a/.github/workflows/swiftly-update.yaml b/.github/workflows/swiftly-update.yaml deleted file mode 100644 index 70f10881..00000000 --- a/.github/workflows/swiftly-update.yaml +++ /dev/null @@ -1,84 +0,0 @@ -name: Check SwiftlyS2 Release - -on: - workflow_dispatch: - description: "Manually trigger SwiftlyS2 update check" - schedule: - - cron: "0 6 * * 1" - -jobs: - check-version: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout code - uses: actions/checkout@v7 - - - name: Resolve current and latest SwiftlyS2 versions - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - CURRENT=$(grep -oP 'SWIFTLYS2_VERSION="\K[^"]+' apps/swiftly/Dockerfile) - LATEST=$(curl -sSL \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GH_TOKEN" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/swiftly-solution/swiftlys2/releases?per_page=40" \ - | jq -r '[.[] | select(.prerelease == false) | select(.tag_name | test("-beta") | not)] | .[0].tag_name') - echo "CURRENT=$CURRENT" >> "$GITHUB_ENV" - echo "LATEST=$LATEST" >> "$GITHUB_ENV" - echo "current=$CURRENT latest=$LATEST" - - # A job that goes green every week while doing nothing is how the csproj - # pins drifted behind the runtime in the first place, so a deliberate skip - # says so in the run log. - - name: Report a deliberate beta pin - if: contains(env.CURRENT, '-beta') - run: | - echo "::notice::pinned to $CURRENT (prerelease); leaving it alone. Latest stable is $LATEST." - - # The runtime zip and EVERY plugin's nuget must move together or the ABI - # breaks. The csproj list is discovered rather than written down: this step - # used to name apps/swiftly alone, so when the practice plugin arrived with - # its own pin it silently stayed a version behind the runtime it gets - # loaded into. - # - # A deliberate beta pin outranks "latest stable": this only ever picks a - # non-prerelease, so left alone it walks a beta back to the release before - # it and takes whatever the beta was pinned for with it. - - name: Update Dockerfile and csprojs - if: >- - env.LATEST != '' && env.LATEST != 'null' && env.CURRENT != env.LATEST - && !contains(env.CURRENT, '-beta') - run: | - set -euo pipefail - NUGET_VERSION="${LATEST#v}" - - sed -i "s|SWIFTLYS2_VERSION=\"[^\"]*\"|SWIFTLYS2_VERSION=\"${LATEST}\"|" apps/swiftly/Dockerfile - grep -q "SWIFTLYS2_VERSION=\"${LATEST}\"" apps/swiftly/Dockerfile \ - || { echo "::error::could not set SWIFTLYS2_VERSION in apps/swiftly/Dockerfile"; exit 1; } - - git config user.name github-actions - git config user.email github-actions@github.com - git add apps/swiftly/Dockerfile - - # `|| true` because grep exits 1 when it matches nothing, and - # `set -e` would abort the step before the friendly error below -- - # which is the whole reason that branch exists. - CSPROJS=$(grep -rl 'Include="SwiftlyS2.CS2"' --include='*.csproj' apps || true) - if [ -z "$CSPROJS" ]; then - echo "::error::no csproj references SwiftlyS2.CS2 -- the pin pattern must have changed" - exit 1 - fi - - for csproj in $CSPROJS; do - sed -i "s|` version from `apps/swiftly/src/FiveStack.csproj` on GitHub — the release we actually ship — and fetches that version's gamedata from SwiftlyS2 at run time, so it tracks the source of truth rather -than a value that could drift. `swiftly-update.yaml` bumps that pin on a schedule and its -`GITHUB_TOKEN` push does not rebuild this image, so baking the version in would go stale. +than a value that could drift. `dependency-update.yaml` bumps that pin on a schedule and +rebuilds only the swiftly image, never this one, so baking the version in would go stale. Fetching the gamedata needs network access during the run either way. Resolution order: `--swiftly-ref ` (validate a specific SwiftlyS2 release) beats diff --git a/apps/gamedata-validator/main.py b/apps/gamedata-validator/main.py index 0c39e51c..01dce58f 100644 --- a/apps/gamedata-validator/main.py +++ b/apps/gamedata-validator/main.py @@ -39,7 +39,7 @@ # SwiftlyS2's signatures live in the framework release we ship, which is pinned by the # SwiftlyS2.CS2 in apps/swiftly/src/FiveStack.csproj. Read at runtime, -# never baked: swiftly-update.yaml bumps that pin without rebuilding this image. +# never baked: dependency-update.yaml bumps that pin without rebuilding this image. FIVESTACK_CSPROJ = ( "https://raw.githubusercontent.com/5stackgg/game-server/" "{ref}/apps/swiftly/src/FiveStack.csproj" diff --git a/apps/swiftly/Dockerfile b/apps/swiftly/Dockerfile index 563ccb91..3d8916af 100644 --- a/apps/swiftly/Dockerfile +++ b/apps/swiftly/Dockerfile @@ -152,8 +152,8 @@ ENV HUD_WORKSHOP_ID="3791548068" # ARG, not ENV: the download below happens once at build time, so these are set # with --build-arg. As ENV they read as runtime knobs beside HUD_WORKSHOP_ID and # would silently do nothing when overridden at docker run. -ARG ADDONS_MANAGER_VERSION="v2.0.3" -ARG ADDONS_MANAGER_URL=https://github.com/SwiftlyS2-Plugins/AddonsManager/releases/download/${ADDONS_MANAGER_VERSION}/AddonsManager.zip +ARG ADDONS_MANAGER_VERSION="v2.0.6" +ARG ADDONS_MANAGER_URL=https://github.com/SwiftlyS2-Plugins/AddonsManager/releases/download/${ADDONS_MANAGER_VERSION}/AddonsManager-${ADDONS_MANAGER_VERSION}.zip # steamcmd's 32-bit deps and .NET's libicu67 already ship in the sniper image # as i386 multiarch packages, so no lib32* / libicu-dev here.