add pipeline

This commit is contained in:
2026-08-27 14:47:00 +02:00
parent a464c3c247
commit b0413d51a7
5 changed files with 279 additions and 0 deletions
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
release_name="$(jq -r '.release.name // ""' "$GITHUB_EVENT_PATH")"
jq -r '.release.body // ""' "$GITHUB_EVENT_PATH" > release-artifacts/changelog.md
if [[ -z "${release_name//[[:space:]]/}" ]]; then
release_name="Ascend: Ailments ${RELEASE_TAG}"
fi
if ! grep -q '[^[:space:]]' release-artifacts/changelog.md; then
echo "::error::The GitHub release needs a non-empty description; it is used as the CurseForge changelog."
exit 1
fi
case "${RELEASE_TAG,,}" in
*-alpha*) release_type="alpha" ;;
*)
if [[ "${RELEASE_PRERELEASE,,}" == "true" ]]; then
release_type="beta"
else
release_type="release"
fi
;;
esac
delimiter="release_name_$(date +%s%N)"
{
echo "display_name<<$delimiter"
echo "$release_name"
echo "$delimiter"
echo "release_type=$release_type"
} >> "$GITHUB_OUTPUT"
echo "Prepared $release_type metadata for $RELEASE_TAG."
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
set -euo pipefail
required_variables=(
CHANGELOG_FILE
CURSEFORGE_API_TOKEN
CURSEFORGE_PROJECT_ID
DISPLAY_NAME
JAR_PATH
MINECRAFT_VERSION
RELEASE_TYPE
)
for variable in "${required_variables[@]}"; do
if [[ -z "${!variable:-}" ]]; then
echo "::error::$variable is required for the CurseForge upload."
exit 1
fi
done
if [[ ! "$CURSEFORGE_PROJECT_ID" =~ ^[0-9]+$ ]]; then
echo "::error::CURSEFORGE_PROJECT_ID must be the numeric project ID from the CurseForge project page."
exit 1
fi
if [[ ! -f "$JAR_PATH" || ! -f "$CHANGELOG_FILE" ]]; then
echo "::error::The release JAR or changelog file is missing."
exit 1
fi
if [[ "$RELEASE_TYPE" != "alpha" && "$RELEASE_TYPE" != "beta" && "$RELEASE_TYPE" != "release" ]]; then
echo "::error::RELEASE_TYPE must be alpha, beta, or release."
exit 1
fi
metadata_file="$(mktemp)"
response_file="$(mktemp)"
trap 'rm -f "$metadata_file" "$response_file"' EXIT
jq -n \
--rawfile changelog "$CHANGELOG_FILE" \
--arg display_name "$DISPLAY_NAME" \
--arg minecraft_version "$MINECRAFT_VERSION" \
--arg release_type "$RELEASE_TYPE" \
'{
changelog: $changelog,
changelogType: "markdown",
displayName: $display_name,
gameVersionNames: [$minecraft_version, "Forge", "Client", "Server"],
releaseType: $release_type,
relations: {
projects: [
{
slug: "ascend",
projectID: "1383429",
type: "optionalDependency"
}
]
}
}' > "$metadata_file"
upload_url="https://minecraft.curseforge.com/api/projects/${CURSEFORGE_PROJECT_ID}/upload-file"
if ! curl \
--silent \
--show-error \
--fail-with-body \
--retry 3 \
--retry-delay 2 \
--header "X-Api-Token: ${CURSEFORGE_API_TOKEN}" \
--form "metadata=<${metadata_file};type=application/json" \
--form "file=@${JAR_PATH};type=application/java-archive" \
--output "$response_file" \
"$upload_url"; then
echo "::error::CurseForge rejected the upload. Response:"
cat "$response_file" >&2
exit 1
fi
file_id="$(jq -er '.id' "$response_file")"
echo "Uploaded $(basename "$JAR_PATH") to CurseForge as file ID $file_id."
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -euo pipefail
property() {
local key="$1"
awk -F= -v key="$key" '$1 == key { sub(/^[^=]*=/, ""); print; exit }' gradle.properties
}
mod_id="$(property mod_id)"
mod_version="$(property mod_version)"
minecraft_version="$(property minecraft_version)"
if [[ -z "$mod_id" || -z "$mod_version" || -z "$minecraft_version" ]]; then
echo "::error::mod_id, mod_version or minecraft_version is missing from gradle.properties."
exit 1
fi
expected_tag="v${mod_version}"
if [[ -n "${RELEASE_TAG:-}" && "$RELEASE_TAG" != "$expected_tag" ]]; then
echo "::error::Release tag '$RELEASE_TAG' does not match mod_version '$mod_version'. Expected '$expected_tag'."
exit 1
fi
jar_path="build/libs/${mod_id}-${mod_version}.jar"
if [[ ! -f "$jar_path" ]]; then
echo "::error::Expected release artifact '$jar_path' was not produced."
find build/libs -maxdepth 1 -type f -print 2>/dev/null || true
exit 1
fi
mods_toml="$(unzip -p "$jar_path" META-INF/mods.toml)"
if ! grep -Fq "modId=\"${mod_id}\"" <<<"$mods_toml"; then
echo "::error::The built JAR does not contain the expected mod ID '$mod_id'."
exit 1
fi
if ! grep -Fq "version=\"${mod_version}\"" <<<"$mods_toml"; then
echo "::error::The built JAR does not contain the expected version '$mod_version'."
exit 1
fi
{
echo "jar_name=$(basename "$jar_path")"
echo "jar_path=$jar_path"
echo "minecraft_version=$minecraft_version"
echo "mod_version=$mod_version"
} >> "$GITHUB_OUTPUT"
echo "Verified $jar_path (Minecraft $minecraft_version, version $mod_version)."
+115
View File
@@ -0,0 +1,115 @@
name: Build and publish
env:
CURSEFORGE_PROJECT_ID: "1668190"
on:
push:
branches:
- "**"
pull_request:
workflow_dispatch:
release:
types:
- published
permissions:
contents: read
concurrency:
group: ailments-${{ github.workflow }}-${{ github.event.release.tag_name || github.ref }}
cancel-in-progress: ${{ github.event_name != 'release' }}
jobs:
build:
name: Test and build Java 17 JAR
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
jar_name: ${{ steps.artifact.outputs.jar_name }}
minecraft_version: ${{ steps.artifact.outputs.minecraft_version }}
mod_version: ${{ steps.artifact.outputs.mod_version }}
steps:
- name: Check out source
uses: actions/checkout@v6
- name: Set up Java 17
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "17"
- name: Set up and validate Gradle
uses: gradle/actions/setup-gradle@v6
- name: Make Gradle wrapper executable
run: chmod +x gradlew
- name: Run tests and build the reobfuscated JAR
run: ./gradlew clean test build --no-daemon --stacktrace
- name: Verify version and release artifact
id: artifact
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: bash .github/scripts/verify-release-artifact.sh
- name: Create SHA-256 checksum
env:
JAR_PATH: ${{ steps.artifact.outputs.jar_path }}
run: |
cd "$(dirname "$JAR_PATH")"
sha256sum "$(basename "$JAR_PATH")" > "$(basename "$JAR_PATH").sha256"
- name: Upload workflow artifact
uses: actions/upload-artifact@v7
with:
name: ascend-ailments-${{ github.run_id }}
if-no-files-found: error
retention-days: 30
path: |
${{ steps.artifact.outputs.jar_path }}
${{ steps.artifact.outputs.jar_path }}.sha256
publish:
name: Publish GitHub and CurseForge release
if: github.event_name == 'release' && github.event.action == 'published'
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
steps:
- name: Check out released source
uses: actions/checkout@v6
- name: Download verified release artifact
uses: actions/download-artifact@v8
with:
name: ascend-ailments-${{ github.run_id }}
path: release-artifacts
- name: Prepare release metadata
id: release
env:
RELEASE_PRERELEASE: ${{ github.event.release.prerelease }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: bash .github/scripts/prepare-release-metadata.sh
- name: Attach JAR and checksum to the GitHub release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$RELEASE_TAG" "release-artifacts/${{ needs.build.outputs.jar_name }}" "release-artifacts/${{ needs.build.outputs.jar_name }}.sha256" --clobber
- name: Upload JAR to CurseForge
env:
CHANGELOG_FILE: release-artifacts/changelog.md
CURSEFORGE_API_TOKEN: ${{ secrets.CURSEFORGE_API_TOKEN }}
DISPLAY_NAME: ${{ steps.release.outputs.display_name }}
JAR_PATH: release-artifacts/${{ needs.build.outputs.jar_name }}
MINECRAFT_VERSION: ${{ needs.build.outputs.minecraft_version }}
RELEASE_TYPE: ${{ steps.release.outputs.release_type }}
run: bash .github/scripts/publish-curseforge.sh
+3
View File
@@ -3,6 +3,9 @@
Forge 1.20.1 library mod providing Soul Rot, Bleed, Fracture, Fear, Charm, Taunt, Overcharm, and Winded. Forge 1.20.1 library mod providing Soul Rot, Bleed, Fracture, Fear, Charm, Taunt, Overcharm, and Winded.
The mod ID is `ascend_ailments`; Ascend is optional. The mod ID is `ascend_ailments`; Ascend is optional.
Release builds are tested and published through GitHub Actions. The required one-time CurseForge setup and release
process are documented in [docs/RELEASING.md](docs/RELEASING.md).
## Public API ## Public API
Normal callers should use `net.fretux.ailments.api.AilmentApi`, for example: Normal callers should use `net.fretux.ailments.api.AilmentApi`, for example: