Add GitHub Actions workflow to build and deploy plugin to OMCSI#1948
Add GitHub Actions workflow to build and deploy plugin to OMCSI#1948
Conversation
Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a new GitHub Actions workflow (.github/workflows/deploy.yml) that automatically builds the Medieval Factions plugin JAR using Gradle and deploys it to an omcsi (open-mc-server-infrastructure) instance. The workflow triggers on pushes to a configurable deploy branch (defaulting to main) and supports manual dispatch.
Changes:
- Added a new CI/CD workflow file that builds the plugin, locates the output JAR, and deploys it via a
POSTrequest to the omcsi deploy API with bearer authentication - Includes input validation for required secrets/variables and HTTP status code handling with descriptive error messages
- Supports configurable deploy branch via a repository variable (
DEPLOY_BRANCH)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.github/workflows/deploy.yml
Outdated
| run: ./gradlew build | ||
|
|
||
| - name: Locate built JAR | ||
| id: locate-jar | ||
| run: | | ||
| # Use find to reliably locate the shadow JAR, excluding any | ||
| # *-sources / *-javadoc JARs. | ||
| JAR_FILE=$(find build/libs -maxdepth 1 -name '*.jar' \ | ||
| ! -name '*-sources.jar' \ | ||
| ! -name '*-javadoc.jar' \ | ||
| -print -quit) | ||
| if [ -z "${JAR_FILE}" ]; then | ||
| echo "❌ No JAR found in build/libs/" | ||
| exit 1 | ||
| fi | ||
| echo "jar_file=${JAR_FILE}" >> "$GITHUB_OUTPUT" | ||
| echo "✅ Found JAR: ${JAR_FILE}" |
There was a problem hiding this comment.
The find command picks the first JAR it encounters, but build/libs/ will contain both the regular JAR (medieval-factions-5.7.2.jar) and the shadow/fat JAR (medieval-factions-5.7.2-all.jar) since the shadow plugin sets archiveClassifier.set('all') in build.gradle. The order find returns files is non-deterministic, so this may deploy the regular JAR (without bundled dependencies) instead of the shadow JAR, which would fail at runtime.
You should either:
- Target the shadow JAR specifically by matching
*-all.jar(e.g.,find build/libs -name '*-all.jar' -print -quit), or - Use
./gradlew shadowJaras the build command (consistent withpublish-release.yml) and only match the shadow JAR.
| run: ./gradlew build | |
| - name: Locate built JAR | |
| id: locate-jar | |
| run: | | |
| # Use find to reliably locate the shadow JAR, excluding any | |
| # *-sources / *-javadoc JARs. | |
| JAR_FILE=$(find build/libs -maxdepth 1 -name '*.jar' \ | |
| ! -name '*-sources.jar' \ | |
| ! -name '*-javadoc.jar' \ | |
| -print -quit) | |
| if [ -z "${JAR_FILE}" ]; then | |
| echo "❌ No JAR found in build/libs/" | |
| exit 1 | |
| fi | |
| echo "jar_file=${JAR_FILE}" >> "$GITHUB_OUTPUT" | |
| echo "✅ Found JAR: ${JAR_FILE}" | |
| run: ./gradlew shadowJar | |
| - name: Locate built JAR | |
| id: locate-jar | |
| run: | | |
| # Use find to reliably locate the shadow/fat JAR (with the `-all` classifier). | |
| JAR_FILE=$(find build/libs -maxdepth 1 -name '*-all.jar' -print -quit) | |
| if [ -z "${JAR_FILE}" ]; then | |
| echo "❌ No shadow JAR (-all.jar) found in build/libs/" | |
| exit 1 | |
| fi | |
| echo "jar_file=${JAR_FILE}" >> "$GITHUB_OUTPUT" | |
| echo "✅ Found shadow JAR: ${JAR_FILE}" |
.github/workflows/deploy.yml
Outdated
| - name: Set up JDK 17 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: temurin |
There was a problem hiding this comment.
The existing workflows in this repository (medieval-factions.yml and publish-release.yml) both use the zulu JDK distribution. This workflow uses temurin instead. For consistency across workflows, consider using zulu here as well (see .github/workflows/publish-release.yml:24 and .github/workflows/medieval-factions.yml:17).
| distribution: temurin | |
| distribution: zulu |
| on: | ||
| push: | ||
| workflow_dispatch: |
There was a problem hiding this comment.
The on: push trigger without any branch filter will cause this workflow to appear (as skipped) for every push to every branch in the repository. While the if condition correctly gates execution, this adds noise to the Actions tab. Consider adding a branch filter that covers the expected deploy branch(es), e.g. branches: [main], and still keep the if condition as a safeguard for the variable-based override. Alternatively, if supporting arbitrary DEPLOY_BRANCH values is important, the current approach is acceptable but worth documenting.
.github/workflows/deploy.yml
Outdated
| run: | | ||
| PLUGIN_JAR_NAME="${{ vars.PLUGIN_JAR_NAME }}" |
There was a problem hiding this comment.
${{ vars.PLUGIN_JAR_NAME }} is interpolated directly into the shell script, which means if the variable contains shell metacharacters (e.g., spaces, semicolons, backticks), it could break the script or lead to injection. Consider assigning it to an environment variable using the env: block (similar to how DEPLOY_TOKEN and DEPLOY_URL are handled) instead of using direct ${{ }} interpolation in the run: block.
| run: | | |
| PLUGIN_JAR_NAME="${{ vars.PLUGIN_JAR_NAME }}" | |
| PLUGIN_JAR_NAME: ${{ vars.PLUGIN_JAR_NAME }} | |
| run: | |
.github/workflows/deploy.yml
Outdated
| --header "Authorization: Bearer ${DEPLOY_TOKEN}" \ | ||
| --form "pluginName=${PLUGIN_JAR_NAME}" \ | ||
| --form "file=@${JAR_FILE}" \ | ||
| --form "branch=${{ github.ref_name }}" \ |
There was a problem hiding this comment.
Similarly to PLUGIN_JAR_NAME, ${{ github.ref_name }} on this line is directly interpolated into the shell script. Branch names can contain characters that are special in shell (e.g., single quotes). This is a script injection risk. Consider passing these values via the env: block and referencing them as shell variables instead.
|
@copilot address comments |
…jection safety Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
All review comments addressed in b8d5e13:
|
|
@copilot Ponder (https://www.github.com/Dans-Plugins/Ponder) must be built from source and installed to Maven locally; the Maven repo is currently down |
…ency resolution Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
Addressed in 99dd43c. The deploy workflow now clones |
|
@copilot The |
…, add Gradle caching and build retries Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
... Fixed in 0660c24. The root cause was JitPack being tried before
|
Adds a CI/CD workflow that builds the plugin JAR via Gradle and deploys it to an omcsi instance.
DEPLOY_BRANCH(default:main) + manualworkflow_dispatch./gradlew shadowJar/ shadow JAR (*-all.jar) frombuild/libs/2.0.0and installs to Maven local before building (therepo.dansplugins.comMaven repository is currently down)gradle/actions/setup-gradle@v3for Gradle dependency caching (consistent withpublish-release.yml)${OMCSI_DEPLOY_URL}/api/plugins/deploywith bearer authPLUGIN_JAR_NAME,OMCSI_DEPLOY_URL,OMCSI_DEPLOY_TOKEN, or non-200 responses (401 → auth error, 400 → bad request)vars.PLUGIN_JAR_NAME,github.ref_name,github.server_url/github.repository) are passed via theenv:block to prevent shell injectionAdditional
build.gradlechangesmavenLocal()to repositories so locally-installed Ponder artifacts can be resolvedcontentfiltering (includeGroupByRegex 'com\\.github\\..*') so JitPack is only queried forcom.github.*artifacts — this prevents JitPack timeouts from blocking resolution of rpkit and other non-GitHub artifacts from their proper repositoriesRequired repo configuration
OMCSI_DEPLOY_URLOMCSI_DEPLOY_TOKENDEPLOY_AUTH_TOKENfrom omcsi.envPLUGIN_JAR_NAMEDEPLOY_BRANCHmain)Modeled after the Activity Tracker deploy workflow, adjusted for this project's Gradle/JDK 17 toolchain and consistent with the existing
publish-release.ymlworkflow (Zulu JDK,shadowJartask).Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.