diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fc19480e..d2c16342 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,9 +3,7 @@ updates: - package-ecosystem: gradle directory: "/" schedule: - interval: daily - time: "08:34" - timezone: "Asia/Yerevan" + interval: "weekly" open-pull-requests-limit: 10 - package-ecosystem: "github-actions" directory: "/" diff --git a/.github/workflows/action-lint.yml b/.github/workflows/action-lint.yml new file mode 100644 index 00000000..a2ca8265 --- /dev/null +++ b/.github/workflows/action-lint.yml @@ -0,0 +1,15 @@ + +name: GitHub Actions lint +on: + push: + pull_request: + +jobs: + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Check workflow files + uses: docker://rhysd/actionlint:latest + with: + args: -color diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 00000000..270ca46a --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,13 @@ +name: "Dependabot Automerge" + +on: + pull_request: + branches: [master] + +jobs: + automerge: + uses: jensborch/workflows/.github/workflows/dependabot-automerge.yml@main + permissions: + pull-requests: write + contents: write + secrets: inherit diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 2a7bf6ab..00000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Build -permissions: - checks: write - pull-requests: write -on: - push: - branches: - - master - - 3.x - pull_request: - types: [ opened, synchronize, reopened ] -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up JDK 8 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: 8 - cache: 'gradle' - - name: Build - run: ./gradlew build - - uses: codecov/codecov-action@v4 - with: - verbose: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..731f9102 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,13 @@ +name: Build + +on: + workflow_dispatch: + push: + branches: [master] + pull_request: + +jobs: + build: + uses: jensborch/workflows/.github/workflows/gradle-build.yml@main + with: + java-version: 8 diff --git a/.github/workflows/delete-workflow-runs.yml b/.github/workflows/delete-workflow-runs.yml new file mode 100644 index 00000000..4fbbc41b --- /dev/null +++ b/.github/workflows/delete-workflow-runs.yml @@ -0,0 +1,20 @@ +name: Delete old workflow runs +on: + schedule: + - cron: '0 0 1 * *' +# Run monthly, at 00:00 on the 1st day of month. + +jobs: + del_runs: + runs-on: ubuntu-latest + permissions: + actions: write + contents: read + steps: + - name: Delete workflow runs + uses: Mattraks/delete-workflow-runs@v2 + with: + token: ${{ github.token }} + repository: ${{ github.repository }} + retain_days: 30 + keep_minimum_runs: 6 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml deleted file mode 100644 index 91916b91..00000000 --- a/.github/workflows/gradle-wrapper-validation.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: "Validate Gradle Wrapper" -on: [pull_request] - -jobs: - validation: - name: "Validation" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v3 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..3317c34d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,14 @@ +name: Publish + +on: + push: + branches: [master] + +jobs: + call-workflow: + uses: jensborch/workflows/.github/workflows/gradle-publish.yml@main + secrets: inherit + permissions: + contents: write + with: + java-version: 8 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 50f2dfea..1064d980 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,33 +1,16 @@ name: Release + on: - workflow_dispatch: - inputs: - version: - description: 'The release version' - required: true + push: + branches: + - "releases/**" jobs: - build: - name: Release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up JDK 8 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: 8 - - name: Build - run: ./gradlew build - - name: Configure Git Author - run: | - git config user.name "GitHub Actions" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - name: Release - env: - RELEASE_VERSION: ${{ github.event.inputs.version }} - ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} - ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} - ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} - ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} - run: ./gradlew release -Prelease.useAutomaticVersion=true -Prelease.releaseVersion=$RELEASE_VERSION + call-workflow: + uses: jensborch/workflows/.github/workflows/gradle-release.yml@main + secrets: inherit + permissions: + contents: write + pull-requests: write + with: + java-version: 8 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..3660660b --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,73 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '28 3 * * 6' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0 + with: + sarif_file: results.sarif diff --git a/build.gradle.kts b/build.gradle.kts index f7400228..18cc96d9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,6 @@ plugins { signing id("io.github.gradle-nexus.publish-plugin") version "2.0.0" id("org.javacc.javacc") version "3.0.2" - id("net.researchgate.release") version "3.0.2" } repositories { @@ -102,8 +101,8 @@ publishing { signing { isRequired = (version as String).endsWith("SNAPSHOT") - val signingKey = findProperty("signingKey") as String? - val signingPassword = findProperty("signingPassword") as String? + val signingKey = findProperty("SIGNING_KEY") as String? + val signingPassword = findProperty("SIGNING_PASSWORD") as String? useInMemoryPgpKeys(signingKey, signingPassword) sign(publishing.publications["java"]) @@ -115,18 +114,12 @@ nexusPublishing { val baseUri = uri("https://oss.sonatype.org") nexusUrl.set(baseUri.resolve("/service/local/")) snapshotRepositoryUrl.set(baseUri.resolve("/content/repositories/snapshots/")) + username = findProperty("SONATYPE_USERNAME") as String? + password = findProperty("SONATYPE_PASSWORD") as String? } } } -release { - tagTemplate.set("v\${version}") - git { - requireBranch.set("master") - pushToRemote.set("origin") - } -} - tasks { @@ -169,9 +162,42 @@ tasks { named("sourcesJar") { dependsOn(compileJavacc) } +} + +val newVersion: String? by project +tasks.register("bumpVersion") { + this.doFirst { + bumpVersion("gradle.properties", "version=") + bumpVersion("README.adoc", "version: ", true) + } +} + +tasks.register("toSnapshot") { + this.doFirst { + val file = file("gradle.properties") + val snapshot = version.toString().contains("-SNAPSHOT") + if (!snapshot) { + file.readText().apply { + println("Adding SNAPSHOT") + val content = this.replace("version=$version", "version=$version-SNAPSHOT") + file.writeText(content) + } + } + } +} - named("afterReleaseBuild") { - dependsOn("publishToSonatype", "closeAndReleaseSonatypeStagingRepository") +fun bumpVersion(fileName: String, versionPattern: String, removeSnapshot: Boolean = false) { + val file = file(fileName) + val snapshot = version.toString().contains("-SNAPSHOT") + val newVersion = takeIf { newVersion.isNullOrBlank() }?.let { + val versionArray = version.toString().removeSuffix("-SNAPSHOT").split(".") + "${versionArray[0]}.${versionArray[1]}.${if (snapshot) versionArray.last().toInt() else versionArray.last().toInt().plus(1)}" + } ?: newVersion + val oldVersion = if (snapshot && removeSnapshot) version.toString().removeSuffix("-SNAPSHOT") else version.toString() + println("Bumping from version $oldVersion to $newVersion in $fileName") + file.readText().apply { + val content = this.replace("$versionPattern$oldVersion", "$versionPattern$newVersion") + file.writeText(content) } }