diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 0000000..15ffaaa --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,76 @@ +# +# CI build that assembles artifacts and runs tests. +# If validation is successful this workflow releases from the main dev branch. +# +# - skipping CI: add [skip ci] to the commit message +# - skipping release: add [skip release] to the commit message +# +# Partially inspired by the GitHub Actions script for mockito/mockito +# https://github.com/mockito/mockito/blob/main/.github/workflows/ci.yml +# + +name: CI/CD + +on: + push: + branches: [ master, dev ] + pull_request: + branches: [ master, dev ] + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - name: 1. Clone repository + id: clone + uses: actions/checkout@v2 + with: + fetch-depth: '0' # https://github.com/shipkit/shipkit-changelog#fetch-depth-on-ci + - name: 2. Set up JDK 11 + id: jdk + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + - name: 3. Build with Gradle + id: build + run: | + chmod +x gradlew + ./gradlew build + echo "::set-output name=version::v$(./gradlew version -q)" + echo "::set-output name=is_new_version::$(./gradlew isNewVersion -q)" + - name: 4. Upload built .jar as artifact + id: upload_jar + uses: actions/upload-artifact@v2.2.4 + with: + name: power-projectiles + path: build/libs/power-projectiles-*.jar + if-no-files-found: error + - name: 5. Generate current changelog + id: changelog + run: ./gradlew generateChangelog + - name: 6. Upload current changelog as artifact + id: upload_changelog + uses: actions/upload-artifact@v2.2.4 + with: + name: changelog + path: build/changelog-clean.md + if-no-files-found: warn + - name: 7. Publish Draft Release + id: release + if: steps.build.outputs.is_new_version == 'true' + && github.event_name == 'push' + && github.ref == 'refs/heads/master' + && github.repository == 'jhale1805/power-projectiles' + && !contains(toJSON(github.event.commits.*.message), '[skip release]') + uses: softprops/action-gh-release@v1 + with: + draft: True + tag_name: ${{ steps.build.outputs.version }} + body_path: build/changelog-clean.md + files: build/libs/power-projectiles-*.jar + fail_on_unmatched_files: True + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: jhale1805/power-projectiles diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml deleted file mode 100644 index 0b884e3..0000000 --- a/.github/workflows/gradle.yml +++ /dev/null @@ -1,41 +0,0 @@ -# This workflow will build a Java project with Gradle -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle - -name: Java CI with Gradle - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v2 - with: - java-version: '11' - distribution: 'adopt' - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Build with Gradle - run: ./gradlew build - - name: Upload built .jar as artifact - uses: actions/upload-artifact@v2.2.4 - with: - name: power-projectiles - path: build/libs/power-projectiles-*.jar - if-no-files-found: error - - name: Publish draft release - uses: softprops/action-gh-release@v1 - with: - draft: True - files: build/libs/power-projectiles-*.jar - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPOSITORY: jhale1805/power-projectiles diff --git a/build.gradle b/build.gradle index 131a752..2a37188 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,9 @@ buildscript { mavenCentral() } dependencies { - classpath 'org.yaml:snakeyaml:1.29' + classpath 'org.yaml:snakeyaml:1.29' // To manipulate the plugin.yml + // auto-version MUST be here so I can apply it *after* setting the project version. + classpath 'org.shipkit:shipkit-auto-version:1.1.19' // Discovers last released version } } @@ -12,6 +14,7 @@ buildscript { plugins { id 'java-library' id 'jacoco' + id 'org.shipkit.shipkit-changelog' version '1.1.15' // Auto-generates the Changelog } // Configure the dependencies of this project. @@ -54,17 +57,81 @@ dependencies { } -// Read in the plugin.yml file for the Minecraft Plugin. -// Aided by https://stackoverflow.com/a/48320319/14765128 -import org.yaml.snakeyaml.Yaml; -def pluginConfig = new Yaml().load( new File("src/main/resources/plugin.yml").newInputStream() ) - -jar { - archiveVersion = pluginConfig.version +// Set up global variables. +project.ext { + repository = 'jhale1805/power-projectiles' } +// Project version MUST be manually set *before* applying the auto-version plugin +project.version = getPluginYml().version +apply plugin: 'org.shipkit.shipkit-auto-version' -// Configure Jacoco -// Copied from https://docs.gradle.org/current/userguide/jacoco_plugin.html test { finalizedBy jacocoTestReport // report is always generated after tests run +} + +jar { + archiveVersion = project.version +} + +task version { + doLast { + println project.version + } +} + +task isNewVersion { + doLast { + println isNewVersion() + } +} + +task cleanupChangelog (dependsOn: 'generateChangelog') { + ext { + outputFile = new File(project.buildDir, "changelog-clean.md") + } + + doLast { // i.e. only if `gradle cleanupChangelog` is run + // Clean up the changelog. + def cleanedChangelog = generateChangelog.outputFile.text + cleanedChangelog = cleanedChangelog.replaceAll(/.*<\/sup>\n\n/, "") // Debrand + cleanedChangelog = cleanedChangelog.replaceAll(/####.*\n/, "") // Remove redundant heading. + logger.lifecycle('Saving cleaned up changelog to file: {}', cleanupChangelog.outputFile) + ext.outputFile.write(cleanedChangelog) + } +} + +generateChangelog { + previousRevision = project.ext.'shipkit-auto-version.previous-tag' + githubToken = System.getenv("GITHUB_TOKEN") + repository = project.ext.repository + + finalizedBy cleanupChangelog +} + +boolean isNewVersion() { + def last_released_version = project.ext.'shipkit-auto-version.previous-version' + def latestVersion = mostRecentVersion([last_released_version, project.version]) + def isNew = latestVersion == project.version && latestVersion != last_released_version + logger.lifecycle('Last released version was ' + last_released_version + + ' and current version is ' + project.version + + ' therefore this ' + (isNew ? 'is' : 'is not') + + ' a new version.' ) + return isNew +} + +String mostRecentVersion( List versions ) { + // Copied from https://stackoverflow.com/a/7737400/14765128 + versions.sort( false ) { a, b -> + [a,b]*.tokenize('.')*.collect { it as int }.with { u, v -> + [u,v].transpose().findResult{ x,y-> x<=>y ?: null } ?: u.size() <=> v.size() + } + }[-1] +} + +def getPluginYml() { + // Read in the plugin.yml file for the Minecraft Plugin. + // Aided by https://stackoverflow.com/a/48320319/14765128 + String PLUGIN_YML_PATH = "src/main/resources/plugin.yml" + InputStream pluginYml = new File(PLUGIN_YML_PATH).newInputStream() + return new org.yaml.snakeyaml.Yaml().load(pluginYml) } \ No newline at end of file