forked from SteamWar/SteamWar
Only build and deploy changed projects in CI
Every project gets a checkAffected task that decides whether it has to
be rebuilt. A project is affected when one of these changed:
- its own files, or paths it adds with an affected { } block
- the versions of its resolved dependencies
- a project it depends on
- the root project, which owns the shared build and CI files
Projects list what they ship in a deploy { } block, and can add
afterDeploy commands there. Jars are now byte-reproducible. Only files
whose hash differs from the deployed one are uploaded, and only their
afterDeploy commands are run.
The deploy workflow diffs against the last deployed commit, which is
stored on the server with the dependency versions. PR builds diff
against the merge base. Shared setup steps moved into composite actions
under .gitea/actions.
This commit is contained in:
+76
-100
@@ -7,84 +7,25 @@ on:
|
||||
- version/*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
deploy:
|
||||
name: Build and deploy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v6
|
||||
- name: Setup Java 8
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v5
|
||||
fetch-depth: 0
|
||||
- name: Setup build
|
||||
uses: ./.gitea/actions/setup-build
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
- name: Setup Java 17
|
||||
uses: actions/setup-java@v5
|
||||
maven-credentials: ${{ secrets.SW_MAVEN_CREDENTIALS }}
|
||||
- name: Setup SSH
|
||||
uses: ./.gitea/actions/setup-ssh
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
- name: Setup Maven Repository
|
||||
env:
|
||||
SW_MAVEN_CREDENTIALS: ${{ secrets.SW_MAVEN_CREDENTIALS }}
|
||||
run: |
|
||||
echo "$SW_MAVEN_CREDENTIALS" > steamwar.properties
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew clean build --no-daemon --no-build-cache --refresh-dependencies
|
||||
|
||||
- name: Stage deploy artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
rm -rf deploy
|
||||
mkdir -p deploy
|
||||
|
||||
cp "AccessWidener/build/libs/AccessWidener-all.jar" "deploy/AccessWidener.jar"
|
||||
cp "BauSystem/build/libs/BauSystem-all.jar" "deploy/BauSystem.jar"
|
||||
cp "FightSystem/build/libs/FightSystem-all.jar" "deploy/FightSystem.jar"
|
||||
cp "KotlinCore/build/libs/KotlinCore-all.jar" "deploy/KotlinCore.jar"
|
||||
cp "TNTLeague/build/libs/TNTLeague.jar" "deploy/TNTLeague.jar"
|
||||
cp "LobbySystem/build/libs/LobbySystem.jar" "deploy/LobbySystem.jar"
|
||||
cp "MissileWars/build/libs/MissileWars.jar" "deploy/MissileWars.jar"
|
||||
cp "Realtime/build/libs/Realtime.jar" "deploy/RealTime.jar"
|
||||
cp "SchematicSystem/build/libs/SchematicSystem-all.jar" "deploy/SchematicSystem.jar"
|
||||
cp "SpigotCore/build/libs/SpigotCore-all.jar" "deploy/SpigotCore.jar"
|
||||
cp "Teamserver/build/libs/Teamserver.jar" "deploy/Builder.jar"
|
||||
cp "TowerRun/build/libs/TowerRun.jar" "deploy/TowerRun.jar"
|
||||
cp "VelocityCore/Persistent/build/libs/Persistent.jar" "deploy/PersistentVelocityCore.jar"
|
||||
cp "VelocityCore/Dependencies/build/libs/Dependencies-all.jar" "deploy/DependenciesVelocityCore.jar"
|
||||
cp "VelocityCore/build/libs/VelocityCore-all.jar" "deploy/VelocityCore.jar"
|
||||
cp "WebsiteBackend/build/libs/WebsiteBackend-all.jar" "deploy/website-api.jar"
|
||||
cp "CLI/build/distributions/sw.zip" "deploy/sw.zip"
|
||||
|
||||
- name: Upload deploy artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: steamwar-jars
|
||||
path: deploy/
|
||||
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Download deploy artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: steamwar-jars
|
||||
path: deploy
|
||||
host: ${{ secrets.DEPLOY_HOST }}
|
||||
user: ${{ secrets.DEPLOY_USER }}
|
||||
port: ${{ secrets.DEPLOY_PORT }}
|
||||
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
|
||||
- name: Resolve deploy target
|
||||
id: target
|
||||
@@ -106,45 +47,80 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload jars with scp
|
||||
- name: Read deployed state
|
||||
id: deployed
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
DEPLOY_PATH: ${{ steps.target.outputs.path }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
: "${DEPLOY_HOST:?Missing DEPLOY_HOST secret}"
|
||||
: "${DEPLOY_USER:?Missing DEPLOY_USER secret}"
|
||||
: "${DEPLOY_SSH_KEY:?Missing DEPLOY_SSH_KEY secret}"
|
||||
mkdir -p .ci
|
||||
ssh deploy "cat '$DEPLOY_PATH/.dependency-versions' 2>/dev/null || true" > .ci/previous-dependency-versions
|
||||
ssh deploy "cd '$DEPLOY_PATH' 2>/dev/null && sha256sum -- *.jar *.zip 2>/dev/null || true" > .ci/deployed-hashes
|
||||
|
||||
port="${DEPLOY_PORT:-22}"
|
||||
commit="$(ssh deploy "cat '$DEPLOY_PATH/.deployed-commit' 2>/dev/null || true")"
|
||||
if [[ ! "$commit" =~ ^[0-9a-f]{40}$ ]]; then
|
||||
echo "No valid deployed commit found in ${DEPLOY_PATH}"
|
||||
commit=""
|
||||
fi
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
echo "$DEPLOY_SSH_KEY" > ~/.ssh/deploy_key
|
||||
chmod 600 ~/.ssh/deploy_key
|
||||
ssh-keyscan -p "$port" "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
||||
echo "Deployed commit: ${commit:-none}"
|
||||
echo "commit=${commit}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "mkdir -p '$DEPLOY_PATH'"
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "mkdir -p '$DEPLOY_PATH/upload'"
|
||||
scp -i ~/.ssh/deploy_key -P "$port" deploy/* "${DEPLOY_USER}@${DEPLOY_HOST}:$DEPLOY_PATH/upload"
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "rm -f '$DEPLOY_PATH'/*.jar '$DEPLOY_PATH'/*.zip"
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "mv '$DEPLOY_PATH'/upload/* '$DEPLOY_PATH'"
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "rm -r '$DEPLOY_PATH/upload'"
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "chmod o-w '$DEPLOY_PATH'/*"
|
||||
- name: Restart Services
|
||||
- name: Determine affected projects
|
||||
id: affected
|
||||
shell: bash
|
||||
run: bash .gitea/scripts/affected-projects.sh .ci "${{ steps.deployed.outputs.commit }}"
|
||||
|
||||
- name: Build with Gradle
|
||||
if: steps.affected.outputs.tasks != ''
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
TASKS: ${{ steps.affected.outputs.tasks }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
ssh -i ~/.ssh/deploy_key -p "$DEPLOY_PORT" "${DEPLOY_USER}@${DEPLOY_HOST}" "sudo systemctl restart api.service"
|
||||
ssh -i ~/.ssh/deploy_key -p "$DEPLOY_PORT" "${DEPLOY_USER}@${DEPLOY_HOST}" "unzip -o /jars/current/sw.zip -d /jars"
|
||||
|
||||
read -ra tasks <<< "$TASKS"
|
||||
./gradlew clean "${tasks[@]}" --no-daemon --no-build-cache --refresh-dependencies
|
||||
|
||||
# Only jars whose content differs from the deployed one, so dependents that merely compile against a change stay untouched
|
||||
- name: Stage changed artifacts
|
||||
shell: bash
|
||||
run: bash .gitea/scripts/stage-artifacts.sh .ci .ci/jars "${{ steps.affected.outputs.projects }}"
|
||||
|
||||
- name: Deploy
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_PATH: ${{ steps.target.outputs.path }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
ssh deploy "mkdir -p '$DEPLOY_PATH'"
|
||||
if compgen -G ".ci/jars/*" > /dev/null; then
|
||||
ssh deploy "rm -rf '$DEPLOY_PATH/upload' && mkdir -p '$DEPLOY_PATH/upload'"
|
||||
scp .ci/jars/* "deploy:$DEPLOY_PATH/upload"
|
||||
ssh deploy "mv -f '$DEPLOY_PATH'/upload/* '$DEPLOY_PATH' && rm -r '$DEPLOY_PATH/upload' && chmod o-w '$DEPLOY_PATH'/*"
|
||||
else
|
||||
echo "No changed artifacts to deploy"
|
||||
fi
|
||||
|
||||
# The next run only builds what changed since this commit
|
||||
scp .ci/dependency-versions "deploy:$DEPLOY_PATH/.dependency-versions"
|
||||
ssh deploy "echo '$GITHUB_SHA' > '$DEPLOY_PATH/.deployed-commit'"
|
||||
|
||||
# The afterDeploy commands of the deploy blocks of all projects with changed artifacts
|
||||
- name: Run after deploy commands
|
||||
if: github.ref_name == 'main'
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_PATH: ${{ steps.target.outputs.path }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
while read -r project command; do
|
||||
if grep -qxF "$project" .ci/deployed-projects; then
|
||||
echo "Running '${command}' for ${project}"
|
||||
ssh -n deploy "cd '$DEPLOY_PATH' && ${command}"
|
||||
fi
|
||||
done < .ci/deploy-commands
|
||||
|
||||
@@ -14,35 +14,31 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v6
|
||||
- name: Setup Java 8
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v5
|
||||
fetch-depth: 0
|
||||
- name: Setup build
|
||||
uses: ./.gitea/actions/setup-build
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
- name: Setup Java 17
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
- name: Setup Maven Repository
|
||||
env:
|
||||
SW_MAVEN_CREDENTIALS: ${{ secrets.SW_MAVEN_CREDENTIALS }}
|
||||
maven-credentials: ${{ secrets.SW_MAVEN_CREDENTIALS }}
|
||||
- name: Determine affected projects
|
||||
id: affected
|
||||
shell: bash
|
||||
run: |
|
||||
echo "$SW_MAVEN_CREDENTIALS" > steamwar.properties
|
||||
set -euo pipefail
|
||||
|
||||
base_branch="$(jq -r '.pull_request.base.ref' "$GITHUB_EVENT_PATH")"
|
||||
base="$(git merge-base "origin/${base_branch}" HEAD || true)"
|
||||
bash .gitea/scripts/affected-projects.sh .ci "$base"
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build --no-daemon
|
||||
if: steps.affected.outputs.tasks != ''
|
||||
shell: bash
|
||||
env:
|
||||
TASKS: ${{ steps.affected.outputs.tasks }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
read -ra tasks <<< "$TASKS"
|
||||
./gradlew "${tasks[@]}" --no-daemon
|
||||
|
||||
- name: Merge successful backport PR
|
||||
shell: bash
|
||||
|
||||
Reference in New Issue
Block a user