From 5435762731677747b4be19b3095621049200cafe Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Sat, 25 May 2024 19:02:33 -0500 Subject: [PATCH 01/16] Updates for Java 17 --- .github/build-scan-init.gradle | 2 +- .github/codecov.yml | 11 +- .github/workflows/ci.yml | 242 ++++++++++++------------ .github/workflows/code-coverage.yml | 122 ++++++------ .github/workflows/codeql-analysis.yml | 78 ++++---- .github/workflows/nightly-ci.yml | 120 ++++++------ .github/workflows/nightly-maven-ci.yml | 78 ++++---- .github/workflows/update-maven-repo.yml | 158 ++++++++-------- build.gradle | 8 +- megameklab/build.gradle | 73 ++++--- 10 files changed, 460 insertions(+), 432 deletions(-) diff --git a/.github/build-scan-init.gradle b/.github/build-scan-init.gradle index 703b825f2..11b89d1a3 100644 --- a/.github/build-scan-init.gradle +++ b/.github/build-scan-init.gradle @@ -46,7 +46,7 @@ void configureExtension(extension) { extension.buildScan.with { termsOfServiceUrl = "https://gradle.com/terms-of-service" termsOfServiceAgree = "yes" - + // // After the build scan is published, put on STDOUT the special // GitHub Actions syntax to set an Output Variable for the job diff --git a/.github/codecov.yml b/.github/codecov.yml index bf2d8a70a..f9fd9f313 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -4,16 +4,16 @@ coverage: status: project: default: - target: auto # auto compares coverage to the previous base commit - threshold: 1% # the leniency in hitting the target - informational: true # makes project checks informational only, not failing + target: auto # auto compares coverage to the previous base commit + threshold: 1% # the leniency in hitting the target + informational: true # makes project checks informational only, not failing patch: default: - informational: true # makes patch checks informational only, not failing + informational: true # makes patch checks informational only, not failing fixes: - - "megameklab/::" # reduce root e.g., "before/path/" => "path/" + - "megameklab/::" # reduce root e.g., "before/path/" => "path/" ignore: - "megamek" @@ -21,4 +21,3 @@ ignore: github_checks: # https://docs.codecov.io/docs/github-checks-beta#disabling-github-checks-patch-annotations-via-yaml annotations: false - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93ff026dd..0e1345611 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ name: MegaMekLab CI with Gradle # Pull Requests being added/updated against master. on: pull_request: - branches: [ master ] + branches: [master] # Setup the Build Scan "VCS" link for all gradle invocations env: @@ -23,126 +23,126 @@ jobs: # Run this job once for each combination in the matrix below. strategy: matrix: - os: [ ubuntu-latest ] # For CI/CD running on *nix is sufficient - java-distribution: [ temurin ] - java-version: [ 11, 17 ] + os: [ubuntu-latest] # For CI/CD running on *nix is sufficient + java-distribution: [temurin] + java-version: [17] fail-fast: false steps: - # Checkout the Pull Request source and put it in: ./megameklab - - uses: actions/checkout@v3 - with: - path: megameklab - - # Setup composite build for MegaMekLab - # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle - - name: Setup Composite Build for MegaMekLab - run: | - echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle - - # Find the repo and branch to use for MM - # - # Output variables: - # - # - mmRepo: The MM repository to use. - # - mmBranch: The MM branch to use. - - name: Find the Right MegaMek Branch - id: find_mm - # Override bash so that it doesn't fail fast (the default) - # if we can't find the branch - shell: bash {0} - # This shell script searches the PR submitter's MM repo for - # a branch that has the same name as the current PR branch. - # If found it sets the `mmRepo` and `mmBranch` step output variables - # to that branch. - run: | - git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} - if [ "$?" == "0" ] - then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "::set-output name=mmRepo::" $4 "/megamek"}' - echo "::set-output name=mmBranch::${{ github.event.pull_request.head.ref }}" - else - echo "::set-output name=mmRepo::MegaMek/megamek" - echo "::set-output name=mmBranch::master" - fi - exit 0 - - # Checkout the latest MegaMek source and put it in: ./megamek - - name: Checkout MegaMek - uses: actions/checkout@v3 - with: - repository: ${{ steps.find_mm.outputs.mmRepo }} - ref: ${{ steps.find_mm.outputs.mmBranch }} - path: megamek - - # Setup the requested Java Distribution and Version from the matrix - - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 - with: - distribution: ${{ matrix.java-distribution }} - java-version: ${{ matrix.java-version }} - - # Make sure we can execute the Gradle wrapper - - name: Grant execute permission for gradlew (*nix or MacOS) - working-directory: megameklab - run: chmod +x gradlew - if: runner.os != 'Windows' - - # Build the MegaMekLab project - # - # Directory layout: - # /megameklab - # /gradlew - # /megamek - # - # Output Variables: - # - buildScanUri - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: build --stacktrace --max-workers=1 --scan - build-root-directory: megameklab - - # If the build step fails, try to upload any test logs in case it was a unit test failure. - # The logs will be relative to the ./megameklab directory. - - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 - if: failure() - with: - name: cd-failure-logs - path: ./megameklab/megameklab/build/reports/ - - # Upload our Code Coverage Reports to CodeCov.io - - name: CodeCov.io Coverage Report - uses: codecov/codecov-action@v3 - with: - directory: ./megameklab/megameklab/build/reports/jacoco/test - fail_ci_if_error: false - verbose: true - - # If we have a buildScanUri comment on the PR - # - # NB: This only works if you're on the main MegaMek\megameklab repo - # for now due to a GitHub Actions limitation. -# CAW: temporarily halted https://github.com/thollander/actions-comment-pull-request/issues/17 -# - name: Comment on PR with Build Scan URI -# uses: thollander/actions-comment-pull-request@master -# if: always() && steps.gradle_build.outputs.buildScanUri != '' -# with: -# message: Build scan available at ${{ steps.gradle_build.outputs.buildScanUri }} -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # Put the Windows Release in an artifact - # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. - - name: Upload Windows Release - uses: actions/upload-artifact@v3 - with: - name: mml-release-win-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} - path: ./megameklab/megameklab/build/distributions/*.zip - - # Put the non-Windows release in an artifact - - name: Upload Nix/Mac Release - uses: actions/upload-artifact@v3 - with: - name: mml-release-nix-mac-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} - path: ./megameklab/megameklab/build/distributions/*.tar + # Checkout the Pull Request source and put it in: ./megameklab + - uses: actions/checkout@v3 + with: + path: megameklab + + # Setup composite build for MegaMekLab + # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle + - name: Setup Composite Build for MegaMekLab + run: | + echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle + + # Find the repo and branch to use for MM + # + # Output variables: + # + # - mmRepo: The MM repository to use. + # - mmBranch: The MM branch to use. + - name: Find the Right MegaMek Branch + id: find_mm + # Override bash so that it doesn't fail fast (the default) + # if we can't find the branch + shell: bash {0} + # This shell script searches the PR submitter's MM repo for + # a branch that has the same name as the current PR branch. + # If found it sets the `mmRepo` and `mmBranch` step output variables + # to that branch. + run: | + git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} + if [ "$?" == "0" ] + then + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "::set-output name=mmRepo::" $4 "/megamek"}' + echo "::set-output name=mmBranch::${{ github.event.pull_request.head.ref }}" + else + echo "::set-output name=mmRepo::MegaMek/megamek" + echo "::set-output name=mmBranch::master" + fi + exit 0 + + # Checkout the latest MegaMek source and put it in: ./megamek + - name: Checkout MegaMek + uses: actions/checkout@v3 + with: + repository: ${{ steps.find_mm.outputs.mmRepo }} + ref: ${{ steps.find_mm.outputs.mmBranch }} + path: megamek + + # Setup the requested Java Distribution and Version from the matrix + - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java-distribution }} + java-version: ${{ matrix.java-version }} + + # Make sure we can execute the Gradle wrapper + - name: Grant execute permission for gradlew (*nix or MacOS) + working-directory: megameklab + run: chmod +x gradlew + if: runner.os != 'Windows' + + # Build the MegaMekLab project + # + # Directory layout: + # /megameklab + # /gradlew + # /megamek + # + # Output Variables: + # - buildScanUri + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: build --stacktrace --max-workers=1 --scan + build-root-directory: megameklab + + # If the build step fails, try to upload any test logs in case it was a unit test failure. + # The logs will be relative to the ./megameklab directory. + - name: Upload Test Logs on Failure + uses: actions/upload-artifact@v3 + if: failure() + with: + name: cd-failure-logs + path: ./megameklab/megameklab/build/reports/ + + # Upload our Code Coverage Reports to CodeCov.io + - name: CodeCov.io Coverage Report + uses: codecov/codecov-action@v3 + with: + directory: ./megameklab/megameklab/build/reports/jacoco/test + fail_ci_if_error: false + verbose: true + + # If we have a buildScanUri comment on the PR + # + # NB: This only works if you're on the main MegaMek\megameklab repo + # for now due to a GitHub Actions limitation. + # CAW: temporarily halted https://github.com/thollander/actions-comment-pull-request/issues/17 + # - name: Comment on PR with Build Scan URI + # uses: thollander/actions-comment-pull-request@master + # if: always() && steps.gradle_build.outputs.buildScanUri != '' + # with: + # message: Build scan available at ${{ steps.gradle_build.outputs.buildScanUri }} + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Put the Windows Release in an artifact + # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. + - name: Upload Windows Release + uses: actions/upload-artifact@v3 + with: + name: mml-release-win-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} + path: ./megameklab/megameklab/build/distributions/*.zip + + # Put the non-Windows release in an artifact + - name: Upload Nix/Mac Release + uses: actions/upload-artifact@v3 + with: + name: mml-release-nix-mac-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} + path: ./megameklab/megameklab/build/distributions/*.tar.gz diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 4009cd523..2e4e9e428 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -9,7 +9,7 @@ name: MegaMekLab CI with Code Coverage # This Action Definition should be triggered only on pushes to master on: push: - branches: [ master ] + branches: [master] # Setup the Build Scan "VCS" link for all gradle invocations env: @@ -23,71 +23,71 @@ jobs: # Run this job once for each combination in the matrix below. strategy: matrix: - os: [ ubuntu-latest ] # For Code QL running on *nix is sufficient - java-distribution: [ temurin ] - java-version: [ 17 ] + os: [ubuntu-latest] # For Code QL running on *nix is sufficient + java-distribution: [temurin] + java-version: [17] steps: - # Checkout the Pull Request source and put it in: ./megameklab - - uses: actions/checkout@v3 - with: - path: megameklab + # Checkout the Pull Request source and put it in: ./megameklab + - uses: actions/checkout@v3 + with: + path: megameklab - # Setup composite build for MegaMekLab - # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle - - name: Setup Composite Build for MegaMekLab - run: | - echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle + # Setup composite build for MegaMekLab + # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle + - name: Setup Composite Build for MegaMekLab + run: | + echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle - # Checkout the latest MegaMek source and put it in: ./megamek - - name: Checkout MegaMek - uses: actions/checkout@v3 - with: - repository: MegaMek/megamek - path: megamek + # Checkout the latest MegaMek source and put it in: ./megamek + - name: Checkout MegaMek + uses: actions/checkout@v3 + with: + repository: MegaMek/megamek + path: megamek - # Setup the requested Java Distribution and Version from the matrix - - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 - with: - distribution: ${{ matrix.java-distribution }} - java-version: ${{ matrix.java-version }} + # Setup the requested Java Distribution and Version from the matrix + - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java-distribution }} + java-version: ${{ matrix.java-version }} - # Make sure we can execute the Gradle wrapper - - name: Grant execute permission for gradlew (*nix or MacOS) - working-directory: megameklab - run: chmod +x gradlew - if: runner.os != 'Windows' + # Make sure we can execute the Gradle wrapper + - name: Grant execute permission for gradlew (*nix or MacOS) + working-directory: megameklab + run: chmod +x gradlew + if: runner.os != 'Windows' - # Build the MegaMekLab project - # - # Directory layout: - # /megameklab - # /gradlew - # /megamek - # - # Output Variables: - # - buildScanUri - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: build --stacktrace --max-workers=1 --scan - build-root-directory: megameklab - - # If the build step fails, try to upload any test logs in case it was a unit test failure. - # - # The logs will be relative to the ./megameklab directory. - - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 - if: failure() - with: - name: cd-failure-logs - path: ./megameklab/megameklab/build/reports/ + # Build the MegaMekLab project + # + # Directory layout: + # /megameklab + # /gradlew + # /megamek + # + # Output Variables: + # - buildScanUri + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: build --stacktrace --max-workers=1 --scan + build-root-directory: megameklab - # Upload our Code Coverage Reports to CodeCov.io - - name: CodeCov.io Coverage Report - uses: codecov/codecov-action@v3 - with: - directory: ./megameklab/megameklab/build/reports/jacoco/test - fail_ci_if_error: false - verbose: true + # If the build step fails, try to upload any test logs in case it was a unit test failure. + # + # The logs will be relative to the ./megameklab directory. + - name: Upload Test Logs on Failure + uses: actions/upload-artifact@v3 + if: failure() + with: + name: cd-failure-logs + path: ./megameklab/megameklab/build/reports/ + + # Upload our Code Coverage Reports to CodeCov.io + - name: CodeCov.io Coverage Report + uses: codecov/codecov-action@v3 + with: + directory: ./megameklab/megameklab/build/reports/jacoco/test + fail_ci_if_error: false + verbose: true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e6570a46b..83631f49e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -12,12 +12,12 @@ name: "CodeQL" on: push: - branches: [ master ] + branches: [master] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: [master] schedule: - - cron: '24 16 * * 4' + - cron: "24 16 * * 4" jobs: analyze: @@ -27,49 +27,49 @@ jobs: # Run this job once for each combination in the matrix below. strategy: matrix: - os: [ ubuntu-latest ] # For Code QL running on *nix is sufficient - language: [ 'java' ] - java-distribution: [ temurin ] - java-version: [ 17 ] + os: [ubuntu-latest] # For Code QL running on *nix is sufficient + language: ["java"] + java-distribution: [temurin] + java-version: [17] fail-fast: false steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v3 - # Setup the requested Java Distribution and Version from the matrix - - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 - with: - distribution: ${{ matrix.java-distribution }} - java-version: ${{ matrix.java-version }} + # Setup the requested Java Distribution and Version from the matrix + - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java-distribution }} + java-version: ${{ matrix.java-version }} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - queries: +security-and-quality + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + queries: +security-and-quality - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild MegaMekLab - uses: github/codeql-action/autobuild@v2 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild MegaMekLab + uses: github/codeql-action/autobuild@v2 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/nightly-ci.yml b/.github/workflows/nightly-ci.yml index 1614676cd..1c66c144f 100644 --- a/.github/workflows/nightly-ci.yml +++ b/.github/workflows/nightly-ci.yml @@ -8,7 +8,7 @@ on: schedule: # Nightly at Midnight (UTC) # ref: https://crontab.guru/every-night - - cron: '0 0 * * *' + - cron: "0 0 * * *" # Setup the Build Scan "VCS" link for all gradle invocations env: @@ -21,75 +21,75 @@ jobs: # Run this job once for each combination in the matrix below. strategy: matrix: - os: [ ubuntu-latest, windows-latest ] - java-distribution: [ temurin ] - java-version: [ 11, 17 ] + os: [ubuntu-latest, windows-latest] + java-distribution: [temurin] + java-version: [17] fail-fast: false name: Nightly MegaMekLab CI ${{ matrix.os }} on ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} steps: - # Checkout the latest source and put it in: ./megameklab - - uses: actions/checkout@v3 - with: - path: megameklab + # Checkout the latest source and put it in: ./megameklab + - uses: actions/checkout@v3 + with: + path: megameklab - # Setup composite build for MegaMekLab - # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle - - name: Setup Composite Build for MegaMekLab - run: | - echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle + # Setup composite build for MegaMekLab + # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle + - name: Setup Composite Build for MegaMekLab + run: | + echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle - # Checkout the latest MegaMek source and put it in: ./megamek - - name: Checkout MegaMek - uses: actions/checkout@v3 - with: - repository: MegaMek/megamek - path: megamek + # Checkout the latest MegaMek source and put it in: ./megamek + - name: Checkout MegaMek + uses: actions/checkout@v3 + with: + repository: MegaMek/megamek + path: megamek - # Setup the requested Java Distribution and Version from the matrix - - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 - with: - distribution: ${{ matrix.java-distribution }} - java-version: ${{ matrix.java-version }} + # Setup the requested Java Distribution and Version from the matrix + - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java-distribution }} + java-version: ${{ matrix.java-version }} - # Don't run this for Windows. - - name: Grant execute permission for gradlew (*nix or MacOS) - working-directory: megameklab - run: chmod +x gradlew - if: runner.os != 'Windows' + # Don't run this for Windows. + - name: Grant execute permission for gradlew (*nix or MacOS) + working-directory: megameklab + run: chmod +x gradlew + if: runner.os != 'Windows' - # Include --stacktrace to make some build failures easier to figure out. - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: clean build -x test --continue --stacktrace --max-workers=1 --scan - build-root-directory: megameklab + # Include --stacktrace to make some build failures easier to figure out. + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: clean build -x test --continue --stacktrace --max-workers=1 --scan + build-root-directory: megameklab - - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 - if: failure() - with: - name: ${{ matrix.os }}-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }}-ci-failure-logs - path: megameklab/megameklab/build/reports/ + - name: Upload Test Logs on Failure + uses: actions/upload-artifact@v3 + if: failure() + with: + name: ${{ matrix.os }}-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }}-ci-failure-logs + path: megameklab/megameklab/build/reports/ - # Put the non-Windows Release in an artifact - # - # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. - - name: Upload Nix/Mac Releases - uses: actions/upload-artifact@v3 - if: always() && matrix.os == 'ubuntu-latest' - with: - name: mml-release-nix-mac-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} - path: megameklab/megameklab/build/distributions/*.tar + # Put the non-Windows Release in an artifact + # + # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. + - name: Upload Nix/Mac Releases + uses: actions/upload-artifact@v3 + if: always() && matrix.os == 'ubuntu-latest' + with: + name: mml-release-nix-mac-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} + path: megameklab/megameklab/build/distributions/*.tar.gz - # Put the Windows Release in an artifact - # - # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. - - name: Upload Windows Release - uses: actions/upload-artifact@v3 - if: always() && matrix.os == 'windows-latest' - with: - name: mml-release-win-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} - path: megameklab/megameklab/build/distributions/*.zip + # Put the Windows Release in an artifact + # + # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. + - name: Upload Windows Release + uses: actions/upload-artifact@v3 + if: always() && matrix.os == 'windows-latest' + with: + name: mml-release-win-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} + path: megameklab/megameklab/build/distributions/*.zip diff --git a/.github/workflows/nightly-maven-ci.yml b/.github/workflows/nightly-maven-ci.yml index 980b9c918..1e34c6616 100644 --- a/.github/workflows/nightly-maven-ci.yml +++ b/.github/workflows/nightly-maven-ci.yml @@ -8,7 +8,7 @@ on: schedule: # Nightly at Midnight (UTC) # ref: https://crontab.guru/every-night - - cron: '0 0 * * *' + - cron: "0 0 * * *" # Setup the Build Scan "VCS" link for all gradle invocations # @@ -24,51 +24,51 @@ jobs: # Run this job once for each combination in the matrix below. strategy: matrix: - os: [ ubuntu-latest, windows-latest ] - java-distribution: [ temurin ] - java-version: [ 11, 17 ] + os: [ubuntu-latest, windows-latest] + java-distribution: [temurin] + java-version: [17] fail-fast: false name: Nightly MegaMekLab Maven CI ${{ matrix.os }} on ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} steps: - # Checkout the latest source and put it in: ./megameklab - - uses: actions/checkout@v3 - with: - path: megameklab + # Checkout the latest source and put it in: ./megameklab + - uses: actions/checkout@v3 + with: + path: megameklab - # Composite Build is NOT setup for this job. + # Composite Build is NOT setup for this job. - # Checkout the latest MegaMek source and put it in: ./megamek - - name: Checkout MegaMek - uses: actions/checkout@v3 - with: - repository: MegaMek/megamek - path: megamek + # Checkout the latest MegaMek source and put it in: ./megamek + - name: Checkout MegaMek + uses: actions/checkout@v3 + with: + repository: MegaMek/megamek + path: megamek - # Setup the requested Java Distribution and Version from the matrix - - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 - with: - distribution: ${{ matrix.java-distribution }} - java-version: ${{ matrix.java-version }} + # Setup the requested Java Distribution and Version from the matrix + - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java-distribution }} + java-version: ${{ matrix.java-version }} - # Don't run this for Windows. - - name: Grant execute permission for gradlew (*nix or MacOS) - working-directory: megameklab - run: chmod +x gradlew - if: runner.os != 'Windows' - - # Include --stacktrace to make some build failures easier to figure out. - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: clean build --continue --stacktrace --max-workers=1 --scan - build-root-directory: megameklab + # Don't run this for Windows. + - name: Grant execute permission for gradlew (*nix or MacOS) + working-directory: megameklab + run: chmod +x gradlew + if: runner.os != 'Windows' - - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 - if: failure() - with: - name: ${{ matrix.os }}-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }}-maven-ci-failure-logs - path: megameklab/megameklab/build/reports/ + # Include --stacktrace to make some build failures easier to figure out. + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: clean build --continue --stacktrace --max-workers=1 --scan + build-root-directory: megameklab + + - name: Upload Test Logs on Failure + uses: actions/upload-artifact@v3 + if: failure() + with: + name: ${{ matrix.os }}-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }}-maven-ci-failure-logs + path: megameklab/megameklab/build/reports/ diff --git a/.github/workflows/update-maven-repo.yml b/.github/workflows/update-maven-repo.yml index acd302eac..b2d91772d 100644 --- a/.github/workflows/update-maven-repo.yml +++ b/.github/workflows/update-maven-repo.yml @@ -1,12 +1,12 @@ -# This workflow updates the MML Maven Repo on push to master +# This workflow updates the MML Maven Repo on push to master name: Update Maven Repo on: push: - branches: [ master ] + branches: [master] paths: - - 'megameklab/src/**' - - 'megameklab/resources/**' + - "megameklab/src/**" + - "megameklab/resources/**" jobs: update_maven_repo: @@ -15,84 +15,84 @@ jobs: # Run this job once for each combination in the matrix below. strategy: matrix: - os: [ ubuntu-latest ] # For Maven Repository Update running on *nix is sufficient - java-distribution: [ temurin ] - java-version: [ 17 ] + os: [ubuntu-latest] # For Maven Repository Update running on *nix is sufficient + java-distribution: [temurin] + java-version: [17] steps: - # Put the MML repo in a subfolder to make updating the Maven repo easier - - uses: actions/checkout@v3 - with: - path: megameklab - - # Grab the MM repo too - - uses: actions/checkout@v3 - with: - repository: MegaMek/megamek - path: megamek + # Put the MML repo in a subfolder to make updating the Maven repo easier + - uses: actions/checkout@v3 + with: + path: megameklab - # Setup composite build for MML - # see: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle - - name: Setup Composite Build for MML - working-directory: megameklab - run: | - echo "includeBuild '../megamek'" >settings_local.gradle + # Grab the MM repo too + - uses: actions/checkout@v3 + with: + repository: MegaMek/megamek + path: megamek - # Setup the requested Java Distribution and Version from the matrix - - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 - with: - distribution: ${{ matrix.java-distribution }} - java-version: ${{ matrix.java-version }} + # Setup composite build for MML + # see: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle + - name: Setup Composite Build for MML + working-directory: megameklab + run: | + echo "includeBuild '../megamek'" >settings_local.gradle - # Make sure we can execute the Gradle wrapper - - name: Grant execute permission for gradlew (*nix or MacOS) - working-directory: megameklab - run: chmod +x gradlew - if: runner.os != 'Windows' + # Setup the requested Java Distribution and Version from the matrix + - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java-distribution }} + java-version: ${{ matrix.java-version }} - # Create the actual maven repo bits with Gradle - - name: Publish Maven Repo with Gradle - working-directory: megameklab - run: ./gradlew publishPublishMMLibraryPublicationToMavenRepository - - # Get the current Maven repo contents - - name: Checkout Maven Repo - if: github.repository == 'MegaMek/megameklab' - uses: actions/checkout@v3 - with: - repository: MegaMek/mavenrepo - path: mavenrepo - - # Create an update - - name: Copy Maven Outputs to Repo - if: github.repository == 'MegaMek/megameklab' - working-directory: megameklab/megameklab/build/mavenrepo/ - run: | - cp -r . ../../../../mavenrepo/ - - # In case we run into an issue, use git status to help us understand what happened. - - name: Inspect git status output - if: github.repository == 'MegaMek/megameklab' - working-directory: mavenrepo - run: | - git status - - # Add the changes under the username and email of the user who pushed the code - - name: Commit changes to the Maven Repo - if: github.repository == 'MegaMek/megameklab' - working-directory: mavenrepo - run: | - git add . - git config user.email ${{ github.event.pusher.email }} - git config user.name ${{ github.event.pusher.name }} - git commit -m "MegaMek ${{ github.event.after }}" -m "${{ github.event.compare }}" - - # Use an SSH deploy key (with write privs) to update the maven repo - - name: Setup SSH and Push changes to the Maven Repo - if: github.repository == 'MegaMek/megameklab' - working-directory: mavenrepo - run: | - eval "$(ssh-agent -s)" - ssh-add - <<< "${{ secrets.MAVEN_REPO_DEPLOY_KEY }}" - git push "git@github.com:MegaMek/mavenrepo.git" HEAD:master + # Make sure we can execute the Gradle wrapper + - name: Grant execute permission for gradlew (*nix or MacOS) + working-directory: megameklab + run: chmod +x gradlew + if: runner.os != 'Windows' + + # Create the actual maven repo bits with Gradle + - name: Publish Maven Repo with Gradle + working-directory: megameklab + run: ./gradlew publishPublishMMLibraryPublicationToMavenRepository + + # Get the current Maven repo contents + - name: Checkout Maven Repo + if: github.repository == 'MegaMek/megameklab' + uses: actions/checkout@v3 + with: + repository: MegaMek/mavenrepo + path: mavenrepo + + # Create an update + - name: Copy Maven Outputs to Repo + if: github.repository == 'MegaMek/megameklab' + working-directory: megameklab/megameklab/build/mavenrepo/ + run: | + cp -r . ../../../../mavenrepo/ + + # In case we run into an issue, use git status to help us understand what happened. + - name: Inspect git status output + if: github.repository == 'MegaMek/megameklab' + working-directory: mavenrepo + run: | + git status + + # Add the changes under the username and email of the user who pushed the code + - name: Commit changes to the Maven Repo + if: github.repository == 'MegaMek/megameklab' + working-directory: mavenrepo + run: | + git add . + git config user.email ${{ github.event.pusher.email }} + git config user.name ${{ github.event.pusher.name }} + git commit -m "MegaMek ${{ github.event.after }}" -m "${{ github.event.compare }}" + + # Use an SSH deploy key (with write privs) to update the maven repo + - name: Setup SSH and Push changes to the Maven Repo + if: github.repository == 'MegaMek/megameklab' + working-directory: mavenrepo + run: | + eval "$(ssh-agent -s)" + ssh-add - <<< "${{ secrets.MAVEN_REPO_DEPLOY_KEY }}" + git push "git@github.com:MegaMek/mavenrepo.git" HEAD:master diff --git a/build.gradle b/build.gradle index 776437c31..7ff334765 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,12 @@ plugins { - id 'org.ajoberstar.grgit' version '5.0.0' + id 'org.ajoberstar.grgit' version '5.2.2' } allprojects { apply plugin: 'java' - sourceCompatibility = 11 - targetCompatibility = 11 + sourceCompatibility = 17 + targetCompatibility = 17 repositories { mavenLocal() @@ -22,7 +22,7 @@ allprojects { subprojects { group = 'org.megamek' - version = '0.49.20-SNAPSHOT' + version = '0.50.0-SNAPSHOT' } ext { diff --git a/megameklab/build.gradle b/megameklab/build.gradle index 3180534bb..0769364de 100644 --- a/megameklab/build.gradle +++ b/megameklab/build.gradle @@ -3,7 +3,7 @@ import java.time.LocalDateTime plugins { id 'application' id 'maven-publish' - id 'edu.sc.seis.launch4j' version '2.5.4' + id 'edu.sc.seis.launch4j' version '3.0.5' id 'jacoco' } @@ -29,32 +29,32 @@ sourceSets { dependencies { implementation "org.megamek:megamek${mmBranchTag}:${version}" - implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0' - implementation 'org.apache.logging.log4j:log4j-core:2.20.0' - implementation 'org.apache.pdfbox:pdfbox:2.0.27' - implementation ('org.apache.xmlgraphics:batik-bridge:1.14') { + implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2' + implementation 'org.apache.logging.log4j:log4j-core:2.23.1' + implementation 'org.apache.pdfbox:pdfbox:2.0.31' + implementation ('org.apache.xmlgraphics:batik-bridge:1.17') { // We don't need the python and javascript engine taking up space exclude group: 'org.python', module: 'jython' exclude group: 'org.mozilla', module: 'rhino' exclude group: 'xml-apis' } - implementation ('org.apache.xmlgraphics:batik-codec:1.14') { + implementation ('org.apache.xmlgraphics:batik-codec:1.17') { exclude group: 'xml-apis' } - implementation ('org.apache.xmlgraphics:batik-dom:1.14') { + implementation ('org.apache.xmlgraphics:batik-dom:1.17') { exclude group: 'xml-apis' } - implementation 'org.apache.xmlgraphics:batik-rasterizer:1.14' - implementation 'org.apache.xmlgraphics:batik-svggen:1.14' - implementation ('org.apache.xmlgraphics:fop:2.7') { + implementation 'org.apache.xmlgraphics:batik-rasterizer:1.17' + implementation 'org.apache.xmlgraphics:batik-svggen:1.17' + implementation ('org.apache.xmlgraphics:fop:2.9') { // We don't need this proprietary module exclude group: 'com.sun.media', module: 'jai-codec' exclude group: 'xml-apis' } - testImplementation 'org.mockito:mockito-core:5.2.0' - testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' + testImplementation 'org.mockito:mockito-core:5.12.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' - runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:4.0.2' + runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:4.0.5' //Required for printing scaled vector graphics (SVG) - EclipseIDE Comipatability. runtimeOnly 'xml-apis:xml-apis-ext:1.3.04' @@ -218,21 +218,28 @@ distributions { createExe { description = 'Create Windows executable that wraps MegaMekLab jar' mainClassName = project.mainClassName - jar = "${project.tasks.getByName("jar").archiveFile.get()}" + jarTask = project.tasks.jar icon = "${projectDir}/data/images/misc/megameklab.ico" internalName = 'MegaMekLab' + downloadUrl = 'https://adoptium.net/temurin/releases/?os=windows&arch=x64' + supportUrl = 'https://megamek.org' + copyright = '2024 MegaMek Development Team' + companyName = "MegaMek Development Team" classpath = ["lib/${mmJar.archiveFileName.get()}"] + project.sourceSets.main.runtimeClasspath.files .findAll { it.name.endsWith(".jar") && !it.name.toLowerCase().startsWith("megamek")} .collect { "${lib}/${it.name}" } - def iniFile = outfile.replace('.exe', '.l4j.ini') outputs.file "${buildDir}/launch4j/${outfile}" - outputs.file "${buildDir}/launch4j/${iniFile}" - doLast { - new File("${buildDir}/${outputDir}/${iniFile}").text = """# Launch4j runtime config -# you can add arguments here that will be processed by the JVM at runtime -${project.ext.mmlJvmOptions.join('\n')} -""" - } + jvmOptions = project.ext.mmlJvmOptions + jreMinVersion = '17' + messagesJreNotFoundError = 'Go here for instructions on installing the correct version of Java: https://github.com/MegaMek/megamek/wiki/Updating-to-Adoptium' +} + +windowsDistTar { + description = 'Creates Windows distribution packaged as a tar.gz archive' + dependsOn stageFiles + dependsOn createExe + archiveExtension = 'tar.gz' + compression = Compression.GZIP } windowsDistZip { @@ -241,6 +248,12 @@ windowsDistZip { dependsOn createExe } +unixDistZip { + description = 'Creates *nix distribution packaged as a zip' + dependsOn stageFiles + dependsOn startScripts +} + unixDistTar { description = 'Creates *nix distribution packaged as a tar ball' dependsOn stageFiles @@ -249,6 +262,22 @@ unixDistTar { compression = Compression.GZIP } +distZip { + description = 'Creates *nix distribution packaged as a zip' + dependsOn stageFiles + dependsOn createStartScripts + dependsOn startScripts +} + +distTar { + description = 'Creates *nix distribution packaged as a tar ball' + dependsOn stageFiles + dependsOn createStartScripts + dependsOn startScripts + archiveExtension = 'tar.gz' + compression = Compression.GZIP +} + // The repository can only be cloned into an empty directory so we need to delete anything left over // from a previous build task deleteMMRepoDir (type: Delete) { From 909054d15f35f00839ea4f79f35b755499de50c5 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Sat, 25 May 2024 21:39:28 -0500 Subject: [PATCH 02/16] Bumped to Gradle 8.7 --- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61624 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 12 ++++++++---- gradlew.bat | 1 + megameklab/build.gradle | 12 +++--------- settings.gradle | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/gradle.properties b/gradle.properties index 114fbe4bd..0e09e4c2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -org.gradle.jvmArgs=-Dfile.encoding=utf-8 +org.gradle.jvmArgs=-Xmx4g -XX:MaxPermSize=2048m -Dfile.encoding=utf-8 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..afba109285af78dbd2a1d187e33ac4f87c76e392 100644 GIT binary patch delta 36621 zcmZ6yQ*|eCn;Lw`wkL zf&=%#8|Xn1!%x?|sNq0B46#8#=#uBhv662yppqlDPyxBx(0=$Ugx`h?A4d-(Vza7P zvN^*|>oa6H$W)cZ$M)OAi#g^}_mnF}k$|KGbUlJ~TM?z~O`{ zid339!M$jCPR4fVvhGMRiASZ5)})S;5~qN~=zxIj;v%${$*+>A`2Fsv59hup=vx=e z{C;Xofr>pfI^8=POzs2r06$GMfupe@I3a3bVP@pMf&)~)MmVFvVmPAY45Ks#*l)OA zy7c4Q%|O|} zWU4#FIFu%Y!L2*W;P1ZNpxc>qW#ZMY6c3=ZNnsu^3X<3-FQwvN^svkLJQs|ETxK|- zcb6;J9Ql*U=xgQ@Qod50HX+7uSwbQHt5JUG`VVTmsd~FAl(6Q>1usr~YfE-yXdXe* zD3P=Cc!le{d>$3KOhao1$!{(T{77(K6(5An^6_yoR;eqT!xPfQMD`RZsmD!qR6RiF zcq_BR*a72`vrYNb1xe}^7kW!GnIjUioJG2i1nB`mQXLiinSdEWnM3lcUH2_Aw&{d; ziLl~u_);2^0-AMJP>mpQYRfmN8v`!)6KPPYp}8R8h8ynRS@w|d3ogiA3$#-)v5{*_ z@xi}wwDJ*yxzjbN`()ZK-^&&rlh^=Fd?t~HF&(Hn@+R60j?1(Ve?bBCn9(RO<460& z)wv@Cazz^E=9la%7s1qX7R5`>rHMktDOWj<-4muT&mz+PA zlenC=WwjzhwdE3&kUcVR=6`(}GNP)(0|=I#G1lyOqS^7{4iR!$^l)uog#rM-ez3hj zsjl?-5XD56b+H}HvJklA8ZPm;o~kS&Flcf}DdSwy%f*)q7re0rA4tJdr21Jh7~ZE&@se#GIe7fYn><&s2jU z4da+9gNi*Tyze-GH1xNcaV0?OZu|`;9=p@+{5H@rzNJ)EGMLs}hUzD23LPw#Xxw+5 zR*j2$(Pvs{trKu41Ij2|X`L_EVbi%G+xDaKhbAP5ueQ%n&h?e zy-`Wzh${RpEM0vhB^gaawSf|q0zZfO{5ZrRE?$ZRk1QZeF+-E)A{nJz{xsBrN;HJv z&)8E6s;z#u?Y4SCO3zq5JCuV01Ljl-@Hk4lFf#Q3Od^z{5pJ#dYFhs)OPg^LbD?#t^KeQ>bdmj(^+|Bd})u7MHxkLBu_VM5RQfli8!TWTODI zVIprFoM!7;c5|NVFXCQ%u^cjqiaD+1vg65RNqV-gI)2quRG_9h*-Q%8vW>}sJf8J8 zu3Pm+x)fk5S8K3C#`pZb)Mn%4mz4r0^_ak1W{O469u9go6$2`*nH&1$V!EG7uDCXc z!1hhC9tX}htb`qmMF^OPq8-VBK=ZuWGd2}D=2q;#)TG)wxg-r@aa9`53Lw;y^~61*V({?qn^L zP_O521s?Fg;{Z8ON@~%}H#0;G(I?j2&3sJE)lV^sXIFLW<)stXDVdIq58=9mQ_6ElZq)a%xu8*Cf(+-OJQB0cAla`{hJ*^+g3aY*E*NvBiM zirQp3jw-!nz60&(1}mpx9@>ycyx%|vHn-5XEKo5&39y?~&S%C=RW5y9m)!;11y0#i z?A$NDuI{je%OR0*Z`e(-tMf&k#!JQA7UyODS`2rRYwK3 zr6Ovz*XHZ}^9MRs>j>-jysW}DZI=1JiK$>Ud-YQLb!SVJLK!uzf8@y?1sJlW4(uO9 z9&8%HQ2;9wnYnT!9{BQqMdhRJV~WhLH4hZrylXRv$x1|Yd0*tAS}#|0-tm(159Ys9 zwCZkG6e1en?wO?nkwq@0m?4myxsf%tjZ)j!fHzZHYtF`f z#Ns*pJKHTW();9Gv1mVij(UeQj1K4vZ!g z696VOSOd2PZ|q!?v4TsfC}^*ME0PnOf@o~hr6yaP+$VzFI_p`S7|YqA z<~NekSgWEo@&3{^j-WwgM8Sg{5vAa`6yPswippOKC|2>BYG-oF9Al2Sfk75Y99nSL zVP`^&$(Z{x-x$(fTtYuA%JD0#Nu@#a634MpoDtfxX#;B#kEp~}!VNH+ya&cqg(#f2 z^t<*TM_ZzG6m4OocXx8aYmn6w&@w`es|5WZKK;m*KRlA*`do3poqHAeBq!?+;{b_O zeq)v+jx+yEF++MMzP##a$bBE!nkMgX#t-b{B=oSH8kdvpbzgr5`z3;AaP4u&Mn*1+ zd@iw0*6(6-EnawX`QrP&K&h5i5tt_S77^MEe5n6PQ7!QO621iHlX*fhO&PB_Xp;p6 z?esnX{R(P$`GVS9E<5^sz^+~j!~lEx6xFMLUEFisc-BY)uYfT!3t@`C<<8sUOu(mV z!^5zQ7gm~&(%4l7WJDXKV6)I~8l{P~m^K5|B*dzT{`kh9=q|7?bCidVepZOu`QXCnk z;NM|JMjKN6%62*yCls};afel-_W1?rE%h|zpD4(V48>Fq*R==;+2aj7(sGUWrE9Q1 zv71rgbW)r z2etaeLu5@q%kMH{TxK1ER#n?@(0+2JrgNNndHLCW1HQlSF@F)KQE-rHDv8yHQVmlK zFPumSU%MbUZ)0bX!V(M-AoEC4c;6`phe{E|^N!-!&S=>RtxwGZ5|?A`8SKV0bI{~Y zme)gjTPf`_OR8w2n-aBRAavp@vTTLSGtOPPezpeDtfDT_cB&EbU(16rhSNPm7D~-q0C}Dl)njB<#dYs zU?UD5%ii&~*QT^s#_aGa z3-se8N2`Ap>%#+#_&P2w7T%A??o)Zvm|^QJ7$Oe%CoLb*tdC2nd2c1ee~gfw26d-(;9(JwIzQvGmSmLRBSMvAZsC6 zOK_mRD@Us$C!TrQ=<#K3bg)-fGCltYCL4ig>U!O78c#j8 z3jsX4PBPzlQ2N%+KNqHCRw5GoU-Q|gYjd9g3w74V;d1WG^Gb=HOD$eYm+)c2gP3qq z&-(#NzSz3f_85Fz(Rf_Y%yLDk=Cvi{zWRfh{kkfET~gd3k9*7F-eT;~h<^+7&_JO9 z^tTv1?A}68(s#lj@Y_}vn{!cn;wN9|gjJ+H19&Oxi)bP`yk~}{V98&BjS?Kqlr0Tb zFin`zvg4kv;uaX~^CB3-=Ulb=7|swP+oU;)NvlC$q6x*T%q(4S=4vIFJlj!ugi=QI z1?%#O}iza{ehy1?7Dg-9MK z(!W|R6eL7?E=5d+mM$^A`WeN%XNlh+%5vZk|BY%eFd!fxA|OBy zS}|q);0{}Q+@hG-BH)+T9-Ur)&IkUvlPJPD;u-`%I!B-!>VmLL+Bf;6J&gZ9EN zx6i0q%a7@+EV0n3=2HphyU`5EbzkPY4pZt~SH_GqJobt;V^ zRJ?c+5&rz*=$^m-9w>;ULALk*(1OV=)$y^3j0Z4kM%fz+49@E!#4=EW zje;mf#6Y)%6p_CWPFP7iu%pop)hYP~UVt{tyE}lokt)krNiRwZML&@KCau{}UOvz& znKq~@)Le&JoQ^HAZ5fwL&d~}pg7NVhml{#Z93gDD62ujXHP5hhQN=-sQ;@-C#W3d} zxa=0^hRkqR;^T%}w=_|{;~0737|;%(&^8zOmLYB-!Daf_Lm^-~FrdplMC}%{88Ea4 z(%74}k1*e1{G;8=2$R@)KJChH=A~@PeJP+X*GZNpf{kzOfk)N0;q17ii*1oPH=N zMM<1&0-rcvgs;<{9BV z)6RB_dS4!hQr$~M>A9Px39GjJd_%aT>-Oq$ogPMv8q#R9D;%v&rMltk++j(9Q!Fi2 z!c{tecZH#}yBUC-}G zhh_P=cwDHR){AH)ho)A+Oy8P-;xf7_9Ysw0DVC`X#fcQ|N2IOLfqGpF5rYW9cTY~K zd}&wgYfy&=hb{H`IAjFmHsw^OcOIr}eL@icPT{KOO_fqk{FI9Ex<9$kG2viMvTv^y zyJ-gI5P?`rx-Wuj;c5fNByM8D5Fy`EurK5ZYmqU|3C}e=r z2-3l%l~)KCH6-k)6;EUxxNwN zRz*n#&Y!_~s)8!bRfq8CT9zGoACGo`hWj656%w2q$N?_sJ6wCSmo3Md?x4jb-3H%d zjz>N;x|5VFjZ|x$%ixFoJ9)yC>p~{4us-2#8M_~N@AQwK=+0r88ZyzIC6rcu1`M>3 zY|VgIaYpE&t(GnYU*Q>9hHrAeMsHK(?;D$&A%2cLEGv5=e|u1ow9zgK{4#dH;uy_F zcyp1iEL%9TbEC}@v-9IZ&9xZaD7rnee|97Bo^R0iu$(h-fEWpRtaP8*DrWvW(!T%r z2#-Su>!McPjadPX5aU-2y9A)=7OYSZ;kz^5nU$BUXYuz%2YN!_J5dLO9$AJK>tq`1 zXdUT59r=`IC8NGqfsv;O;V&%!YmiJZgQi-`J*l*CB@UXo8wPj6Fb8KTEw%LS?zpQo zK~OU(N>KBR@T)G z8$*e}UgPk=2U6JwAjSI;!of1q9E@5ahcHGj>t_>>l|<#GDPzw`kH2Ni(5OHCDl^RKQw3aruGky z#d?w0dJ4Ok`jr>uSWv=m??X*q=e>8yu2m>_eBU3<~NPieD?^a_3K z0-n))DgKxo(@7xcJ?xlj$L&r8tr2zRp>+xm0nRaNIZXtPY*hy*)K7O^EY9%m>` ztn*LJ7beQaY04(^P5g>tgBWUUa?MYGioWz<#;`t7@_IPf^rFh7K@$} zlF>0;C4!$~o3B|hZ)w;U2=zk6jvl4LTr@GK2asS)=ySq-UtdEiyU#h zV$|RhU?b;jp>E0&Op42DpWI03^)MsI=Gfm8<81`-!hRIQw*3d%$47c_$nOirNLV*~ z>^3lTEb|c-R!P=d_E#g6{t#Q2!4^w0S{~_mCoIalJ-5P+qnu4#F+Z3BVOp-e?4~YR zDfft)q+0gMZhdAX($I4Kn!Qvzwo*x-KFOsV07cs!PBlNgVd~(pUw|U-&oG228Lf-{ z%nGG|+;T764g!ibL(K(*pQeYhT=ZIOz36}gpL6-6M90~O>+D2BYXm9#{6*KWWA+o zn0B`~J>_bs=}f2?0?ymLCA;PFr5ggSml?7&epayOT61I((Z79n?%3+!z@N@z)Kjr% zs$WDBB?+mZU1f}$g~>1`0arJq8?-*LGC?s=<=`Ut=lp)JlT_lRYL{{)i&8Nbkk#NW z#mT7U(OTPCm1#@mgI~!ROMTO+p!djQ^NeO_`Q%CG4cP^u*_KuHS9s5HE~!#1s~Bm0 zwIFdG{oHa&^N<>Khh|>`vfe~n1bP#*JFXS(Z@(_A6P&*K{8n!Gp)%9knQ#G?8qBuvK*bqH3W7;!CXZ%bV8%92oP!#<#zfLVq#%Hb zlTlf)M^nPVyL)oeU}sf-sw~I|SO95Twy^m*D}tE5$}-YvRQ&C0lPA*zC^WMbS#X|U zC;4}rEjlewnk~~lm%O4V2)LgL?AIk@4dWvZw-kYl{j;h*i8rYTi&vSnUvuy-XrcS& z31^?-nJ=8Xs#i90*m=lc*k(%mwAYq7o6?<^W2>$hK5rJClQxn3U&GvcTQiBfN{yfS znBWrAr9%}~MD6{fvAlW==mn{6YMkUqhh>e%*&wLP5zm=$FeQ1iLF%KHE;)0sT3tOZ zgX9-X!~t;7P(QV(73g=z`j~Q84HM;1KbuB+Lu;YU z!sWBq4Xy-wnJR>NnHofQquc3S=4$Vv?6mJ^{pu2=2y5&tDo!vO3pS&g&HO<~iH~tkX=guerI_pXsCFi%Foaq8E2WM4B~PNnrYbn+j971ab)fvAqM; z9VTswju(KZ^FPyp?`(iuOLD9}BM@Eifj{epx(aH;7rY9hq)@^e$sEd3mL5C3lya!5i|e;*vz!Bt5PI*(%@&a42`6t z<4Ax>1{1>x^~{gAlLix7?IIOh23Pfx&&^&)V_|;}Hpi4`dc2y$p9*qDxpfbX&iBT^ z&(1(tn0yz+B(5#!2upe=RK2uSjB#(8-{)ptf?k}YTb z_b4;A=u!^gNIv?&<@PUr-=jb8P zwPXi7J5ZIS*e4V>zK6dR7Nba&LD;94|B8-JRp2$m<%X6ZFQ%r!!@US8N_2_V;_y2k zsii1}!58RlFC1_a!(rvADF480F~T|Mqa$cp^x|%2j#p0Nmk#+sbh&kx{zm@a(pD`9 zdQbue0`ds;|BYDC`}ly|R0E|YV~nvMEBu{ROkBD@_448y@J&H5Ft$anXouqH2vpur z{aHFof|L$cN2B;ok6qrRk)j7-#Qn$?0!n)S0x3f*WV~jV+yYKouk!o)0>Co{lHxGn z_!eo(bm(Y3RHdM}S2j|TCS~NQS;gja7u_9yQ9( z9J7=dS}BL5?90^I5fDhKnc5Lgc`S^P$f5o<8t;)Y;Q|363lvzeZas{sCifIyl+!ug zL7|P;S0wTTW;`avYH96#zkah^F>a}w(7mBMMH96YZLpLojeEFB#_bx~1k~Rpmy``8 zg=b`;*&}hqHn z!gS(@w3-5Jup^xq^G07pwj2m*M;4rku)&a=WQKia?|8umB#(Y=dDOf5GN&iP>a zOdR(6@8mg2?rEkBMx)jcz1Wl)n#QxNJ~;0kjAQQbS&qjULn|MAXcH_q)hO6gRL<4e;5xh~6rn(by2S-tX%?Yd_#E=dQ zRrX6)Fl$4KDeu<9)inr}fov=b|1ZoDhF~UD|G_*Am5fSHo$UMzD%qNom;~r@0HjFa z(w{6%DZwsxSo}rX<4lVwfmuibDM9CyJ)B(5$q4B0!8wq&n@>#aVvQv_#G_)V9QdU< zk^+UvPUnhenxUbh?2=1r=#i!1xE7V>z!rl=s4}+#St1T`m#Fgh>7n%RC1#ckac+mu)CzpRbzr zUTI0w^D?S%t})n@bSlnCOAx|Rc;t-c!~p_w7G2PX=>Bd$h5JGykRj;^)9`ATwE+i0_`4uKanz;dkd2I4uat<2X7C6Xx50Cb~am8uA z^T&w=1Lbvhx>p1EO1ErIEz^DSnjP6ya=Cc3)f!74OKv`$BbjE~a=eXtKgZuh?EtO| z16%47Jj792^2d(lGcmluf*dE3%oKE`JQfVRB2bnb(rW2HEVVM^UGSC-^)R?Imx8g`X zWWYai7*@a-)O;&we+Tt}*BBO+C&0pFFX=r}rC>$&ViM}4z&lZ-;4qiJ+Q)i;US*{W zRGL)EjOQs9k_UY6wZ>*Oj0I7pdN+#XmW2>>pF8I-2_*Gvh22R^0~* z*J6X{Q>XtW6rm~Eu^0cW@Mc+~xuPU{FY22I|YoWNATZz*Xv@wH+#ogapGP5u+3;AlSNwm6a@`0O!-m zhWYsR_u4k0B=HFKt&ubYnt~q)@gz?dBTS1-p^TN4rB&~nrRA0|0PqdP5@F?!6Ihv? zv6?8Vl2J-w>AoFUYN8ntUW8&n`Y#DcZ+gPHy>=T&IvTd@@sZwerWYJrGH&%L?zzo0$x!Jl`lP zpc5`O*-}PVGbUpe_=p%xM5lvqK5{Cb9q}h~=|g$uKxjQro-oOVu3x=^AxfZ2t)o>4ftE>2Qc5WAdDszu*G$#V;Ap z^sZ!ZsTv^fDhtCA31I7+TVV|7@D7jOBz=2b%0A;APSd3WM%p;X}YQ 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 O%nF=zbk|6GSN{tyrB9>) delta 35860 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 Date: Mon, 24 Jun 2024 20:54:24 -0500 Subject: [PATCH 03/16] Gradle Updates --- megameklab/build.gradle | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/megameklab/build.gradle b/megameklab/build.gradle index 4fd237fef..40a91c397 100644 --- a/megameklab/build.gradle +++ b/megameklab/build.gradle @@ -60,7 +60,9 @@ dependencies { runtimeOnly 'xml-apis:xml-apis-ext:1.3.04' } -mainClassName = 'megameklab.MegaMekLab' +application { + mainClass = 'megameklab.MegaMekLab' +} ext { mmlJvmOptions = ['-Xmx1024m'] @@ -83,7 +85,7 @@ ext { task mmJar (type: Jar) { description = 'Builds a MegaMek jar from the current source' - dependsOn gradle.includedBuild('megamek').task(':compileTestJava') + dependsOn gradle.includedBuild('megamek').task(':megamek:compileTestJava') archiveFileName = "MegaMek.jar" from "${mmDir}/megamek/build/classes/java/main" @@ -105,7 +107,7 @@ task mmJar (type: Jar) { jar { archiveFileName = "MegaMekLab.jar" manifest { - attributes "Main-Class" : mainClassName + attributes "Main-Class" : application.mainClass attributes "Class-Path" : "${lib}/${mmJar.archiveFileName.get()} " + (project.sourceSets.main.runtimeClasspath.files .findAll { it.name.endsWith(".jar") && !it.name.toLowerCase().startsWith("megamek") } .collect { "${lib}/${it.name}" }.join(' ')) From 371c611c633adef3c54cc0845955a0e897d45f6b Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:01:37 -0500 Subject: [PATCH 04/16] Minor tweaks to build scripts --- .github/build-scan-init.gradle | 19 +++--------- ...epo.yml => update-maven-repo.yml.disabled} | 0 .github/workflows/write-revision.yml | 30 ------------------- 3 files changed, 4 insertions(+), 45 deletions(-) rename .github/workflows/{update-maven-repo.yml => update-maven-repo.yml.disabled} (100%) delete mode 100644 .github/workflows/write-revision.yml diff --git a/.github/build-scan-init.gradle b/.github/build-scan-init.gradle index 11b89d1a3..0566abf5f 100644 --- a/.github/build-scan-init.gradle +++ b/.github/build-scan-init.gradle @@ -23,22 +23,11 @@ initscript { def isTopLevelBuild = gradle.getParent() == null if (isTopLevelBuild) { - def gradleVersion = GradleVersion.current().baseVersion - def atLeastGradle5 = gradleVersion >= GradleVersion.version("5.0") - def atLeastGradle6 = gradleVersion >= GradleVersion.version("6.0") - - if (atLeastGradle6) { - settingsEvaluated { - if (!it.pluginManager.hasPlugin("com.gradle.enterprise")) { - it.pluginManager.apply(GradleEnterprisePlugin) - } - configureExtension(it.extensions["gradleEnterprise"]) - } - } else if (atLeastGradle5) { - rootProject { - pluginManager.apply(BuildScanPlugin) - configureExtension(extensions["gradleEnterprise"]) + settingsEvaluated { + if (!it.pluginManager.hasPlugin("com.gradle.enterprise")) { + it.pluginManager.apply(GradleEnterprisePlugin) } + configureExtension(it.extensions["gradleEnterprise"]) } } diff --git a/.github/workflows/update-maven-repo.yml b/.github/workflows/update-maven-repo.yml.disabled similarity index 100% rename from .github/workflows/update-maven-repo.yml rename to .github/workflows/update-maven-repo.yml.disabled diff --git a/.github/workflows/write-revision.yml b/.github/workflows/write-revision.yml deleted file mode 100644 index 68ae1b3ab..000000000 --- a/.github/workflows/write-revision.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: "Write MML Revision" - -on: - push: - branches: - - master - paths: - # only write the revision for changes that affect program behavior - - '**.gradle' - - 'megameklab/src/**' - - 'megameklab/data/**' - -jobs: - write_hashcode: - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Write latest revision hashcode to file - run: echo ${{ github.sha }} > megameklab/docs/mml-revision.txt - - - name: Commit and Push Changes - run: | - git config --global user.name 'GitHub Actions' - git config --global user.email 'actions@github.com' - git add megameklab/docs/mml-revision.txt - git commit -m 'Update mml-revision.txt' - git push From 1c85b637521e326ecea7505867292409ac394815 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:12:40 -0500 Subject: [PATCH 05/16] Action Updates --- .github/build-scan-init.gradle | 11 +---- .github/workflows/ci.yml | 24 +++++----- .github/workflows/code-coverage.yml | 12 ++--- .github/workflows/codeql-analysis.yml | 45 ++++++++++++++++++- .github/workflows/nightly-ci.yml | 14 +++--- .github/workflows/nightly-maven-ci.yml | 10 ++--- .../workflows/update-maven-repo.yml.disabled | 8 ++-- 7 files changed, 78 insertions(+), 46 deletions(-) diff --git a/.github/build-scan-init.gradle b/.github/build-scan-init.gradle index 0566abf5f..2fda6179a 100644 --- a/.github/build-scan-init.gradle +++ b/.github/build-scan-init.gradle @@ -36,17 +36,8 @@ void configureExtension(extension) { termsOfServiceUrl = "https://gradle.com/terms-of-service" termsOfServiceAgree = "yes" - // - // After the build scan is published, put on STDOUT the special - // GitHub Actions syntax to set an Output Variable for the job - // step: - // - // ::set-output name={variable}::{value} - // - // ref: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-output-parameter - // buildScanPublished { PublishedBuildScan scan -> - println "::set-output name=buildScanUri::${scan.buildScanUri}\n" + echo "name=buildScanUri::${scan.buildScanUri}\n" >> $GITHUB_OUTPUT } } } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e1345611..c74df47f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: steps: # Checkout the Pull Request source and put it in: ./megameklab - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: megameklab @@ -59,17 +59,17 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "::set-output name=mmRepo::" $4 "/megamek"}' - echo "::set-output name=mmBranch::${{ github.event.pull_request.head.ref }}" + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek" >> $GITHUB_OUTPUT}' + echo "name=mmBranch::${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else - echo "::set-output name=mmRepo::MegaMek/megamek" - echo "::set-output name=mmBranch::master" + echo "name=mmRepo::MegaMek/megamek" >> $GITHUB_OUTPUT + echo "name=mmBranch::master" >> $GITHUB_OUTPUT fi exit 0 # Checkout the latest MegaMek source and put it in: ./megamek - name: Checkout MegaMek - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ steps.find_mm.outputs.mmRepo }} ref: ${{ steps.find_mm.outputs.mmBranch }} @@ -77,7 +77,7 @@ jobs: # Setup the requested Java Distribution and Version from the matrix - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} @@ -98,7 +98,7 @@ jobs: # Output Variables: # - buildScanUri - name: Build with Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: build --stacktrace --max-workers=1 --scan build-root-directory: megameklab @@ -106,7 +106,7 @@ jobs: # If the build step fails, try to upload any test logs in case it was a unit test failure. # The logs will be relative to the ./megameklab directory. - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: cd-failure-logs @@ -114,7 +114,7 @@ jobs: # Upload our Code Coverage Reports to CodeCov.io - name: CodeCov.io Coverage Report - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: directory: ./megameklab/megameklab/build/reports/jacoco/test fail_ci_if_error: false @@ -135,14 +135,14 @@ jobs: # Put the Windows Release in an artifact # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. - name: Upload Windows Release - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: mml-release-win-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} path: ./megameklab/megameklab/build/distributions/*.zip # Put the non-Windows release in an artifact - name: Upload Nix/Mac Release - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: mml-release-nix-mac-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} path: ./megameklab/megameklab/build/distributions/*.tar.gz diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 2e4e9e428..59033b0d7 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -29,7 +29,7 @@ jobs: steps: # Checkout the Pull Request source and put it in: ./megameklab - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: megameklab @@ -41,14 +41,14 @@ jobs: # Checkout the latest MegaMek source and put it in: ./megamek - name: Checkout MegaMek - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: MegaMek/megamek path: megamek # Setup the requested Java Distribution and Version from the matrix - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} @@ -69,7 +69,7 @@ jobs: # Output Variables: # - buildScanUri - name: Build with Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: build --stacktrace --max-workers=1 --scan build-root-directory: megameklab @@ -78,7 +78,7 @@ jobs: # # The logs will be relative to the ./megameklab directory. - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: cd-failure-logs @@ -86,7 +86,7 @@ jobs: # Upload our Code Coverage Reports to CodeCov.io - name: CodeCov.io Coverage Report - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: directory: ./megameklab/megameklab/build/reports/jacoco/test fail_ci_if_error: false diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 83631f49e..4cd9112ad 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,11 +35,52 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + # Setup composite build for MegaMekLab + # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle + - name: Setup Composite Build for MegaMekLab + run: | + echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle + + # Find the repo and branch to use for MM + # + # Output variables: + # + # - mmRepo: The MM repository to use. + # - mmBranch: The MM branch to use. + - name: Find the Right MegaMek Branch + id: find_mm + # Override bash so that it doesn't fail fast (the default) + # if we can't find the branch + shell: bash {0} + # This shell script searches the PR submitter's MM repo for + # a branch that has the same name as the current PR branch. + # If found it sets the `mmRepo` and `mmBranch` step output variables + # to that branch. + run: | + git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} + if [ "$?" == "0" ] + then + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek" >> $GITHUB_OUTPUT}' + echo "name=mmBranch::${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT + else + echo "name=mmRepo::MegaMek/megamek" >> $GITHUB_OUTPUT + echo "name=mmBranch::master" >> $GITHUB_OUTPUT + fi + exit 0 + + # Checkout the latest MegaMek source and put it in: ./megamek + - name: Checkout MegaMek + uses: actions/checkout@v4 + with: + repository: ${{ steps.find_mm.outputs.mmRepo }} + ref: ${{ steps.find_mm.outputs.mmBranch }} + path: megamek # Setup the requested Java Distribution and Version from the matrix - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} diff --git a/.github/workflows/nightly-ci.yml b/.github/workflows/nightly-ci.yml index 1c66c144f..978ed1e19 100644 --- a/.github/workflows/nightly-ci.yml +++ b/.github/workflows/nightly-ci.yml @@ -30,7 +30,7 @@ jobs: steps: # Checkout the latest source and put it in: ./megameklab - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: megameklab @@ -42,14 +42,14 @@ jobs: # Checkout the latest MegaMek source and put it in: ./megamek - name: Checkout MegaMek - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: MegaMek/megamek path: megamek # Setup the requested Java Distribution and Version from the matrix - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} @@ -62,13 +62,13 @@ jobs: # Include --stacktrace to make some build failures easier to figure out. - name: Build with Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: clean build -x test --continue --stacktrace --max-workers=1 --scan build-root-directory: megameklab - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{ matrix.os }}-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }}-ci-failure-logs @@ -78,7 +78,7 @@ jobs: # # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. - name: Upload Nix/Mac Releases - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() && matrix.os == 'ubuntu-latest' with: name: mml-release-nix-mac-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} @@ -88,7 +88,7 @@ jobs: # # NB: Due to a GitHub Actions limitation we won't know what the filename is in order to display it somewhere. - name: Upload Windows Release - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() && matrix.os == 'windows-latest' with: name: mml-release-win-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }} diff --git a/.github/workflows/nightly-maven-ci.yml b/.github/workflows/nightly-maven-ci.yml index 1e34c6616..6850339f2 100644 --- a/.github/workflows/nightly-maven-ci.yml +++ b/.github/workflows/nightly-maven-ci.yml @@ -33,7 +33,7 @@ jobs: steps: # Checkout the latest source and put it in: ./megameklab - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: megameklab @@ -41,14 +41,14 @@ jobs: # Checkout the latest MegaMek source and put it in: ./megamek - name: Checkout MegaMek - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: MegaMek/megamek path: megamek # Setup the requested Java Distribution and Version from the matrix - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} @@ -61,13 +61,13 @@ jobs: # Include --stacktrace to make some build failures easier to figure out. - name: Build with Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: clean build --continue --stacktrace --max-workers=1 --scan build-root-directory: megameklab - name: Upload Test Logs on Failure - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{ matrix.os }}-${{ matrix.java-distribution }}-jdk${{ matrix.java-version }}-maven-ci-failure-logs diff --git a/.github/workflows/update-maven-repo.yml.disabled b/.github/workflows/update-maven-repo.yml.disabled index b2d91772d..4a66df437 100644 --- a/.github/workflows/update-maven-repo.yml.disabled +++ b/.github/workflows/update-maven-repo.yml.disabled @@ -21,12 +21,12 @@ jobs: steps: # Put the MML repo in a subfolder to make updating the Maven repo easier - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: megameklab # Grab the MM repo too - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: MegaMek/megamek path: megamek @@ -40,7 +40,7 @@ jobs: # Setup the requested Java Distribution and Version from the matrix - name: Set up ${{ matrix.java-distribution }} JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} @@ -59,7 +59,7 @@ jobs: # Get the current Maven repo contents - name: Checkout Maven Repo if: github.repository == 'MegaMek/megameklab' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: MegaMek/mavenrepo path: mavenrepo From 0f9ad1872c7d3e0ba793923026e8f60758e6c31b Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:17:46 -0500 Subject: [PATCH 06/16] Updates to CI files --- .github/workflows/ci.yml | 18 +++++------------- .github/workflows/code-coverage.yml | 18 +++++------------- .github/workflows/codeql-analysis.yml | 19 +++++-------------- .github/workflows/nightly-ci.yml | 10 +++++----- .github/workflows/nightly-maven-ci.yml | 9 +++++---- 5 files changed, 25 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c74df47f1..0b7804610 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,20 +88,12 @@ jobs: run: chmod +x gradlew if: runner.os != 'Windows' - # Build the MegaMekLab project - # - # Directory layout: - # /megameklab - # /gradlew - # /megamek - # - # Output Variables: - # - buildScanUri + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + - name: Build with Gradle - uses: gradle/gradle-build-action@v3 - with: - arguments: build --stacktrace --max-workers=1 --scan - build-root-directory: megameklab + working-directory: megameklab + run: ./gradlew build --stacktrace --scan # If the build step fails, try to upload any test logs in case it was a unit test failure. # The logs will be relative to the ./megameklab directory. diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 59033b0d7..f3526f882 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -59,20 +59,12 @@ jobs: run: chmod +x gradlew if: runner.os != 'Windows' - # Build the MegaMekLab project - # - # Directory layout: - # /megameklab - # /gradlew - # /megamek - # - # Output Variables: - # - buildScanUri + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + - name: Build with Gradle - uses: gradle/gradle-build-action@v3 - with: - arguments: build --stacktrace --max-workers=1 --scan - build-root-directory: megameklab + working-directory: megameklab + run: ./gradlew build --stacktrace --scan # If the build step fails, try to upload any test logs in case it was a unit test failure. # diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4cd9112ad..fee037495 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -96,21 +96,12 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main queries: +security-and-quality - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild MegaMekLab - uses: github/codeql-action/autobuild@v2 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release + - name: Build with Gradle + working-directory: megameklab + run: ./gradlew build --stacktrace --scan - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/nightly-ci.yml b/.github/workflows/nightly-ci.yml index 978ed1e19..ce5312431 100644 --- a/.github/workflows/nightly-ci.yml +++ b/.github/workflows/nightly-ci.yml @@ -60,12 +60,12 @@ jobs: run: chmod +x gradlew if: runner.os != 'Windows' - # Include --stacktrace to make some build failures easier to figure out. + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + - name: Build with Gradle - uses: gradle/gradle-build-action@v3 - with: - arguments: clean build -x test --continue --stacktrace --max-workers=1 --scan - build-root-directory: megameklab + working-directory: megameklab + run: ./gradlew clean build -x test --continue --stacktrace --scan - name: Upload Test Logs on Failure uses: actions/upload-artifact@v4 diff --git a/.github/workflows/nightly-maven-ci.yml b/.github/workflows/nightly-maven-ci.yml index 6850339f2..e6ca410cd 100644 --- a/.github/workflows/nightly-maven-ci.yml +++ b/.github/workflows/nightly-maven-ci.yml @@ -60,11 +60,12 @@ jobs: if: runner.os != 'Windows' # Include --stacktrace to make some build failures easier to figure out. + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + - name: Build with Gradle - uses: gradle/gradle-build-action@v3 - with: - arguments: clean build --continue --stacktrace --max-workers=1 --scan - build-root-directory: megameklab + working-directory: megameklab + run: ./gradlew clean build --continue --stacktrace --max-workers=1 --scan - name: Upload Test Logs on Failure uses: actions/upload-artifact@v4 From 873098259d8a2f3af0a67fba442f76ab38e7c45a Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:21:58 -0500 Subject: [PATCH 07/16] Possible Path Fixing --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b7804610..a98e4d0c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek" >> $GITHUB_OUTPUT}' + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek"}' >> $GITHUB_OUTPUT echo "name=mmBranch::${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else echo "name=mmRepo::MegaMek/megamek" >> $GITHUB_OUTPUT diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fee037495..1cffa61dc 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -62,7 +62,7 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek" >> $GITHUB_OUTPUT}' + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek"}' >> $GITHUB_OUTPUT echo "name=mmBranch::${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else echo "name=mmRepo::MegaMek/megamek" >> $GITHUB_OUTPUT From 1bb566fbe3a07fe2b93bf774f6668e2b4bcbf491 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:43:08 -0500 Subject: [PATCH 08/16] Possible MegaMek Repo Fix --- .github/workflows/ci.yml | 21 ++++++++------------- .github/workflows/codeql-analysis.yml | 12 ++++++------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a98e4d0c4..c92a94bb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,8 @@ jobs: steps: # Checkout the Pull Request source and put it in: ./megameklab - - uses: actions/checkout@v4 + - name: Checking out MegaMekLab + uses: actions/checkout@v4 with: path: megameklab @@ -59,11 +60,11 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek"}' >> $GITHUB_OUTPUT - echo "name=mmBranch::${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "mmRepo=" $4 "/megamek"}' >> $GITHUB_OUTPUT + echo "mmBranch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else - echo "name=mmRepo::MegaMek/megamek" >> $GITHUB_OUTPUT - echo "name=mmBranch::master" >> $GITHUB_OUTPUT + echo "mmRepo=MegaMek/megamek" >> $GITHUB_OUTPUT + echo "mmBranch=master" >> $GITHUB_OUTPUT fi exit 0 @@ -71,8 +72,8 @@ jobs: - name: Checkout MegaMek uses: actions/checkout@v4 with: - repository: ${{ steps.find_mm.outputs.mmRepo }} - ref: ${{ steps.find_mm.outputs.mmBranch }} + repository: ${{ steps.vars.outputs.mmRepo }} + ref: ${{ steps.vars.outputs.mmBranch }} path: megamek # Setup the requested Java Distribution and Version from the matrix @@ -82,12 +83,6 @@ jobs: distribution: ${{ matrix.java-distribution }} java-version: ${{ matrix.java-version }} - # Make sure we can execute the Gradle wrapper - - name: Grant execute permission for gradlew (*nix or MacOS) - working-directory: megameklab - run: chmod +x gradlew - if: runner.os != 'Windows' - - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1cffa61dc..bf559d39d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -62,11 +62,11 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "name=mmRepo::" $4 "/megamek"}' >> $GITHUB_OUTPUT - echo "name=mmBranch::${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT + echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "mmRepo=" $4 "/megamek"}' >> $GITHUB_OUTPUT + echo "mmBranch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else - echo "name=mmRepo::MegaMek/megamek" >> $GITHUB_OUTPUT - echo "name=mmBranch::master" >> $GITHUB_OUTPUT + echo "mmRepo=MegaMek/megamek" >> $GITHUB_OUTPUT + echo "mmBranch=master" >> $GITHUB_OUTPUT fi exit 0 @@ -74,8 +74,8 @@ jobs: - name: Checkout MegaMek uses: actions/checkout@v4 with: - repository: ${{ steps.find_mm.outputs.mmRepo }} - ref: ${{ steps.find_mm.outputs.mmBranch }} + repository: ${{ steps.vars.outputs.mmRepo }} + ref: ${{ steps.vars.outputs.mmBranch }} path: megamek # Setup the requested Java Distribution and Version from the matrix From 87d2e1e579d62390ed52131cd892d7f681bfcc3d Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:44:41 -0500 Subject: [PATCH 09/16] OUtput the output --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c92a94bb2..9b121f2ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,6 +66,7 @@ jobs: echo "mmRepo=MegaMek/megamek" >> $GITHUB_OUTPUT echo "mmBranch=master" >> $GITHUB_OUTPUT fi + echo $GITHUB_OUTPUT exit 0 # Checkout the latest MegaMek source and put it in: ./megamek From 9e597f77ccacb06a4ccee56e7c8c709028bc84c8 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:57:47 -0500 Subject: [PATCH 10/16] Testing of Outputs --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b121f2ef..60dbdb101 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,10 @@ jobs: ci_cd: runs-on: ${{ matrix.os }} + outputs: + mmRepo: ${{ steps.find_mm.outputs.mmRepo }} + mmBranch: ${{ steps.find_mm.outputs.mmBranch }} + # Run this job once for each combination in the matrix below. strategy: matrix: @@ -49,8 +53,7 @@ jobs: # - mmBranch: The MM branch to use. - name: Find the Right MegaMek Branch id: find_mm - # Override bash so that it doesn't fail fast (the default) - # if we can't find the branch + # Override bash so that it doesn't fail fast (the default) if we can't find the branch shell: bash {0} # This shell script searches the PR submitter's MM repo for # a branch that has the same name as the current PR branch. @@ -60,21 +63,20 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "mmRepo=" $4 "/megamek"}' >> $GITHUB_OUTPUT + echo "mmRepo=${{ github.event.pull_request.head.repo.owner }}/megamek" >> $GITHUB_OUTPUT echo "mmBranch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else echo "mmRepo=MegaMek/megamek" >> $GITHUB_OUTPUT echo "mmBranch=master" >> $GITHUB_OUTPUT fi - echo $GITHUB_OUTPUT exit 0 # Checkout the latest MegaMek source and put it in: ./megamek - name: Checkout MegaMek uses: actions/checkout@v4 with: - repository: ${{ steps.vars.outputs.mmRepo }} - ref: ${{ steps.vars.outputs.mmBranch }} + repository: ${{ steps.find_mm.outputs.mmRepo }} + ref: ${{ steps.find_mm.outputs.mmBranch }} path: megamek # Setup the requested Java Distribution and Version from the matrix From 5ba0c14c31bc7d0b7bc010ee0261a269a1d7df7a Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 21:58:40 -0500 Subject: [PATCH 11/16] owener -> login --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60dbdb101..54e84dcdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,7 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "mmRepo=${{ github.event.pull_request.head.repo.owner }}/megamek" >> $GITHUB_OUTPUT + echo "mmRepo=${{ github.event.pull_request.head.repo.owner.login }}/megamek" >> $GITHUB_OUTPUT echo "mmBranch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else echo "mmRepo=MegaMek/megamek" >> $GITHUB_OUTPUT From f9c0e539578db61b4addc1a46bfea62bf8c0a7a0 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 22:02:01 -0500 Subject: [PATCH 12/16] CodeQL Updates --- .github/workflows/codeql-analysis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index bf559d39d..2c1130c64 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,6 +24,10 @@ jobs: name: Analyze runs-on: ${{ matrix.os }} + outputs: + mmRepo: ${{ steps.find_mm.outputs.mmRepo }} + mmBranch: ${{ steps.find_mm.outputs.mmBranch }} + # Run this job once for each combination in the matrix below. strategy: matrix: @@ -51,8 +55,7 @@ jobs: # - mmBranch: The MM branch to use. - name: Find the Right MegaMek Branch id: find_mm - # Override bash so that it doesn't fail fast (the default) - # if we can't find the branch + # Override bash so that it doesn't fail fast (the default) if we can't find the branch shell: bash {0} # This shell script searches the PR submitter's MM repo for # a branch that has the same name as the current PR branch. @@ -62,7 +65,7 @@ jobs: git ls-remote --exit-code --heads ${{ github.event.pull_request.head.repo.owner.html_url }}/megamek.git ${{ github.event.pull_request.head.ref }} if [ "$?" == "0" ] then - echo "${{ github.event.pull_request.head.repo.owner.html_url }}" | awk -F/ '{print "mmRepo=" $4 "/megamek"}' >> $GITHUB_OUTPUT + echo "mmRepo=${{ github.event.pull_request.head.repo.owner.login }}/megamek" >> $GITHUB_OUTPUT echo "mmBranch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else echo "mmRepo=MegaMek/megamek" >> $GITHUB_OUTPUT From 92138ccca24cfc2201607649e28c3d6884344e87 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 22:03:31 -0500 Subject: [PATCH 13/16] Updated CodeQL Versions --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2c1130c64..552a7edd8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -90,7 +90,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -107,4 +107,4 @@ jobs: run: ./gradlew build --stacktrace --scan - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 From 6e92dce76db89d8367594d92dd9a06ba41c56264 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 22:06:03 -0500 Subject: [PATCH 14/16] Corrected variables for MegaMek --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 552a7edd8..8df05a78d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false steps: - - name: Checkout repository + - name: Checkout MegaMekLab uses: actions/checkout@v4 # Setup composite build for MegaMekLab @@ -77,8 +77,8 @@ jobs: - name: Checkout MegaMek uses: actions/checkout@v4 with: - repository: ${{ steps.vars.outputs.mmRepo }} - ref: ${{ steps.vars.outputs.mmBranch }} + repository: ${{ steps.find_mm.outputs.mmRepo }} + ref: ${{ steps.find_mm.outputs.mmBranch }} path: megamek # Setup the requested Java Distribution and Version from the matrix From f697842d9684d37deacf8dd9c20e9398d02b6443 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 23:03:07 -0500 Subject: [PATCH 15/16] Path fixes for MML --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54e84dcdf..040263091 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle - name: Setup Composite Build for MegaMekLab run: | - echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle + echo "includeBuild '../megamek'" >> ./megameklab/settings_local.gradle # Find the repo and branch to use for MM # diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8df05a78d..718923fec 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle - name: Setup Composite Build for MegaMekLab run: | - echo "includeBuild '../megamek'" >./megameklab/settings_local.gradle + echo "includeBuild '../megamek'" >> ./megameklab/settings_local.gradle # Find the repo and branch to use for MM # From 301d4bf0628ff735dac0d13fe1402e5e9df7cb58 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Fri, 28 Jun 2024 23:07:17 -0500 Subject: [PATCH 16/16] Possible CodeQL Fixes for MML --- .github/workflows/codeql-analysis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 718923fec..2feb3ff7b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -40,6 +40,8 @@ jobs: steps: - name: Checkout MegaMekLab uses: actions/checkout@v4 + with: + path: megameklab # Setup composite build for MegaMekLab # See: https://github.com/MegaMek/megamek/wiki/Working-With-Gradle