Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 10 additions & 68 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: build
name: Builds

on:
push:
Expand All @@ -10,47 +10,41 @@ permissions:
contents: read

env:
COMMON_BRANCH: main
COMMON_BRANCH: common
COMMON_DIR: Dissolver Enhanced (Common)
TARGET_DIR: Dissolver Enhanced (Target)

jobs:
build-common:
name: Build Common
if: ${{ github.ref_name == 'main' }}
if: ${{ github.ref_name == 'common' }}
runs-on: ubuntu-22.04
steps:
- name: Checkout Common
uses: actions/checkout@v4
with:
path: ${{ env.COMMON_DIR }}

- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4
with:
min-wrapper-count: 1

- name: Setup Java 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: microsoft

- name: Setup .NET 6
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x

- name: Build Minecraft Common
working-directory: ${{ env.COMMON_DIR }}/minecraft
run: |
chmod +x ./gradlew
./gradlew build -x test --no-daemon

- name: Build Stardew Valley Common
working-directory: ${{ env.COMMON_DIR }}
run: dotnet build stardewvalley/src/DissolverEnhanced.StardewValley.Common.csproj --configuration Release

- name: Upload Common artifacts
uses: actions/upload-artifact@v7.0.1
with:
Expand All @@ -59,14 +53,13 @@ jobs:

discover-version-branches:
name: Discover Version Branches
if: ${{ github.ref_name == 'main' }}
if: ${{ github.ref_name == 'common' }}
runs-on: ubuntu-22.04
outputs:
branches: ${{ steps.branches.outputs.branches }}
steps:
- name: Checkout Common
uses: actions/checkout@v4

- name: Find build branches
id: branches
shell: bash
Expand All @@ -81,86 +74,64 @@ jobs:

build-all-version-branches:
name: Build ${{ matrix.branch }}
if: ${{ github.ref_name == 'main' && needs.discover-version-branches.outputs.branches != '[]' }}
if: ${{ github.ref_name == 'common' && needs.discover-version-branches.outputs.branches != '[]' }}
needs: discover-version-branches
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
branch: ${{ fromJson(needs.discover-version-branches.outputs.branches) }}

steps:
- name: Checkout Common
uses: actions/checkout@v4
with:
ref: ${{ env.COMMON_BRANCH }}
path: ${{ env.COMMON_DIR }}

- name: Checkout ${{ matrix.branch }}
uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}
path: ${{ env.TARGET_DIR }}

- name: Define artifact name
id: artifact
shell: bash
run: |
echo "name=$(printf '%s' '${{ matrix.branch }}' | tr '/' '-')" >> "$GITHUB_OUTPUT"

- name: Validate Gradle wrappers
if: ${{ startsWith(matrix.branch, 'minecraft/') }}
uses: gradle/actions/wrapper-validation@v4
with:
min-wrapper-count: 2

- name: Select Java version
if: ${{ startsWith(matrix.branch, 'minecraft/') }}
id: java
shell: bash
run: |
case "${{ matrix.branch }}" in
minecraft/forge-1.20.x)
echo "version=17" >> "$GITHUB_OUTPUT"
echo "distribution=temurin" >> "$GITHUB_OUTPUT"
;;
minecraft/fabric-26.1.x)
echo "version=25" >> "$GITHUB_OUTPUT"
echo "distribution=temurin" >> "$GITHUB_OUTPUT"
;;
*)
echo "version=21" >> "$GITHUB_OUTPUT"
echo "distribution=microsoft" >> "$GITHUB_OUTPUT"
;;
esac

echo "version=${{ matrix.branch == 'minecraft/forge-1.20.x' && '17' || matrix.branch == 'minecraft/fabric-26.1.x' && '25' || '21' }}" >> "$GITHUB_OUTPUT"
echo "distribution=${{ (matrix.branch == 'minecraft/forge-1.20.x' || matrix.branch == 'minecraft/fabric-26.1.x') && 'temurin' || 'microsoft' }}" >> "$GITHUB_OUTPUT"
- name: Setup Java ${{ steps.java.outputs.version }}
if: ${{ startsWith(matrix.branch, 'minecraft/') }}
uses: actions/setup-java@v4
with:
java-version: ${{ steps.java.outputs.version }}
distribution: ${{ steps.java.outputs.distribution }}

- name: Build Minecraft ${{ matrix.branch }}
if: ${{ startsWith(matrix.branch, 'minecraft/') }}
working-directory: ${{ env.TARGET_DIR }}
run: |
chmod +x ./gradlew
./gradlew build -x test --no-daemon

- name: Upload Minecraft ${{ matrix.branch }} artifacts
if: ${{ startsWith(matrix.branch, 'minecraft/') }}
uses: actions/upload-artifact@v7.0.1
with:
name: ${{ steps.artifact.outputs.name }}-${{ github.sha }}
path: ${{ env.TARGET_DIR }}/build/libs/

- name: Setup .NET 6
if: ${{ startsWith(matrix.branch, 'stardewvalley/') }}
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x

- name: Build Stardew Valley ${{ matrix.branch }}
if: ${{ startsWith(matrix.branch, 'stardewvalley/') }}
working-directory: ${{ env.TARGET_DIR }}
Expand All @@ -176,7 +147,6 @@ jobs:
cp build/*.dll build/manifest.json "package/DissolverEnhanced/"
cd package
zip -r "../${archive_name}.zip" DissolverEnhanced -x '*.pdb' '*.deps.json' 'ref/*'

- name: Upload Stardew Valley ${{ matrix.branch }} artifacts
if: ${{ startsWith(matrix.branch, 'stardewvalley/') }}
uses: actions/upload-artifact@v7.0.1
Expand All @@ -186,7 +156,7 @@ jobs:

package-all-builds:
name: Package All Builds
if: ${{ github.ref_name == 'main' && needs.build-common.result == 'success' && needs.build-all-version-branches.result == 'success' }}
if: ${{ github.ref_name == 'common' && needs.build-common.result == 'success' && needs.build-all-version-branches.result == 'success' }}
needs:
- build-common
- build-all-version-branches
Expand All @@ -196,34 +166,28 @@ jobs:
uses: actions/download-artifact@v8.0.1
with:
path: downloaded-artifacts

- name: Collect release artifacts
shell: bash
run: |
set -euo pipefail
mkdir -p release-artifacts

while IFS= read -r -d '' jar; do
relative_path="${jar#downloaded-artifacts/}"
target_path="release-artifacts/${relative_path}"
mkdir -p "$(dirname "${target_path}")"
cp "${jar}" "${target_path}"
done < <(find downloaded-artifacts -type f -iname '*.jar' ! -iname '*source*' -print0)

while IFS= read -r -d '' zip_file; do
relative_path="${zip_file#downloaded-artifacts/}"
target_path="release-artifacts/${relative_path}"
mkdir -p "$(dirname "${target_path}")"
cp "${zip_file}" "${target_path}"
done < <(find downloaded-artifacts -type f -iname '*.zip' -print0)

if ! find release-artifacts -type f \( -iname '*.jar' -o -iname '*.zip' \) | grep -q .; then
echo "No release artifacts were found in downloaded artifacts." >&2
exit 1
fi

zip -r "all_builds-${GITHUB_SHA}.zip" release-artifacts

- name: Upload all builds zip
uses: actions/upload-artifact@v7.0.1
with:
Expand All @@ -240,72 +204,51 @@ jobs:
with:
ref: ${{ env.COMMON_BRANCH }}
path: ${{ env.COMMON_DIR }}

- name: Checkout current branch
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
path: ${{ env.TARGET_DIR }}

- name: Define artifact name
id: current-artifact
shell: bash
run: |
echo "name=$(printf '%s' '${{ github.ref_name }}' | tr '/' '-')" >> "$GITHUB_OUTPUT"

- name: Validate Gradle wrappers
if: ${{ startsWith(github.ref_name, 'minecraft/') }}
uses: gradle/actions/wrapper-validation@v4
with:
min-wrapper-count: 2

- name: Select Java version
if: ${{ startsWith(github.ref_name, 'minecraft/') }}
id: current-java
shell: bash
run: |
case "${{ github.ref_name }}" in
minecraft/forge-1.20.x)
echo "version=17" >> "$GITHUB_OUTPUT"
echo "distribution=temurin" >> "$GITHUB_OUTPUT"
;;
minecraft/fabric-26.1.x)
echo "version=25" >> "$GITHUB_OUTPUT"
echo "distribution=temurin" >> "$GITHUB_OUTPUT"
;;
*)
echo "version=21" >> "$GITHUB_OUTPUT"
echo "distribution=microsoft" >> "$GITHUB_OUTPUT"
;;
esac

echo "version=${{ github.ref_name == 'minecraft/forge-1.20.x' && '17' || github.ref_name == 'minecraft/fabric-26.1.x' && '25' || '21' }}" >> "$GITHUB_OUTPUT"
echo "distribution=${{ (github.ref_name == 'minecraft/forge-1.20.x' || github.ref_name == 'minecraft/fabric-26.1.x') && 'temurin' || 'microsoft' }}" >> "$GITHUB_OUTPUT"
- name: Setup Java ${{ steps.current-java.outputs.version }}
if: ${{ startsWith(github.ref_name, 'minecraft/') }}
uses: actions/setup-java@v4
with:
java-version: ${{ steps.current-java.outputs.version }}
distribution: ${{ steps.current-java.outputs.distribution }}

- name: Build current Minecraft branch
if: ${{ startsWith(github.ref_name, 'minecraft/') }}
working-directory: ${{ env.TARGET_DIR }}
run: |
chmod +x ./gradlew
./gradlew build -x test --no-daemon

- name: Upload current Minecraft branch artifacts
if: ${{ startsWith(github.ref_name, 'minecraft/') }}
uses: actions/upload-artifact@v7.0.1
with:
name: ${{ steps.current-artifact.outputs.name }}-${{ github.sha }}
path: ${{ env.TARGET_DIR }}/build/libs/

- name: Setup .NET 6
if: ${{ startsWith(github.ref_name, 'stardewvalley/') }}
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x

- name: Build current Stardew Valley branch
if: ${{ startsWith(github.ref_name, 'stardewvalley/') }}
working-directory: ${{ env.TARGET_DIR }}
Expand All @@ -321,7 +264,6 @@ jobs:
cp build/*.dll build/manifest.json "package/DissolverEnhanced/"
cd package
zip -r "../${archive_name}.zip" DissolverEnhanced -x '*.pdb' '*.deps.json' 'ref/*'

- name: Upload current Stardew Valley branch artifacts
if: ${{ startsWith(github.ref_name, 'stardewvalley/') }}
uses: actions/upload-artifact@v7.0.1
Expand Down
87 changes: 87 additions & 0 deletions .github/workflows/quality-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Quality Gate

on:
push:
branches:
- "**"

permissions:
contents: read

jobs:
duplicate-code:
name: Duplicate Code
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install jscpd
run: npm install --global jscpd@5.0.12
- name: Check for duplicated code
id: duplicate-scan
uses: kucherenko/jscpd@v5.0.12
with:
skip-install: true
path: .
# Locale JSON files are translation data, not duplicated implementation.
threshold: 0
min-lines: 8
min-tokens: 60
ignore-pattern: '(?m)^(?:package|import)\s+[^;\r\n]+;\s*(?:\r?\n|$)'
reporters: console
upload-sarif: false
ignore: '**/.git/**,**/node_modules/**,**/.venv/**,**/vendor/**,**/dist/**,**/build/**,**/coverage/**,**/generated/**,**/src/main/resources/assets/**/lang/**'
- name: Enforce duplicate-code threshold
if: ${{ always() && steps.duplicate-scan.outputs.exit-code != '0' }}
run: |
echo "::error::Duplicate-code threshold exceeded."
exit 1


workflow-integrity:
name: Workflow Tamper Check
runs-on: ubuntu-latest
steps:
- name: Checkout current branch workflow
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
path: current
persist-credentials: false
sparse-checkout: .github/workflows/quality-gate.yml
sparse-checkout-cone-mode: false
- name: Checkout canonical workflow from common
uses: actions/checkout@v7
with:
ref: common
path: canonical
persist-credentials: false
sparse-checkout: .github/workflows/quality-gate.yml
sparse-checkout-cone-mode: false
- name: Compare Quality Gate workflows
shell: bash
run: |
set -euo pipefail
CURRENT="current/.github/workflows/quality-gate.yml"
CANONICAL="canonical/.github/workflows/quality-gate.yml"
if [[ ! -f "$CURRENT" ]]; then
echo "::error file=.github/workflows/quality-gate.yml::Quality Gate workflow is missing from the current branch."
exit 1
fi
if [[ ! -f "$CANONICAL" ]]; then
echo "::error::Canonical Quality Gate workflow is missing from the common branch."
exit 1
fi
if ! cmp --silent "$CANONICAL" "$CURRENT"; then
echo "::error file=.github/workflows/quality-gate.yml::Quality Gate does not match the common branch."
echo
echo "Workflow differences:"
diff \
--unified \
--label "common/.github/workflows/quality-gate.yml" \
--label "current/.github/workflows/quality-gate.yml" \
"$CANONICAL" \
"$CURRENT" || true
exit 1
fi
echo "Quality Gate matches the canonical workflow on common."
Loading
Loading