diff --git a/.config/checkstyle/checkstyle.xml b/.config/checkstyle/checkstyle.xml index 506f37c..43b5290 100644 --- a/.config/checkstyle/checkstyle.xml +++ b/.config/checkstyle/checkstyle.xml @@ -16,7 +16,7 @@ - + @@ -30,10 +30,6 @@ - - - - @@ -43,11 +39,20 @@ + + + + + + + + + @@ -64,6 +69,11 @@ + + + + + @@ -89,7 +99,6 @@ - @@ -118,7 +127,13 @@ + + + + + + @@ -131,11 +146,5 @@ - - - - - - diff --git a/.config/pmd/ruleset.xml b/.config/pmd/ruleset.xml new file mode 100644 index 0000000..88a7b5a --- /dev/null +++ b/.config/pmd/ruleset.xml @@ -0,0 +1,197 @@ + + + + + This ruleset checks the code for discouraged programming constructs. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitattributes b/.gitattributes index dfe0770..9c74e42 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,9 @@ # Auto detect text files and perform LF normalization * text=auto + +# Force sh files to have LF +*.sh text eol=lf + +# Force MVN Wrapper Linux files LF +mvnw text eol=lf +.mvn/wrapper/maven-wrapper.properties text eol=lf diff --git a/.github/.lycheeignore b/.github/.lycheeignore new file mode 100644 index 0000000..dc88a07 --- /dev/null +++ b/.github/.lycheeignore @@ -0,0 +1,3 @@ +# Ignorefile for broken link check +localhost +mvnrepository.com diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..1f1f896 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,69 @@ +name: 🐞 Bug +description: Create a bug report for something that is broken +labels: [bug] +type: bug +body: + - type: markdown + attributes: + value: | + Thank you for reporting a bug. + + Please fill in as much information as possible about your bug so that we don't have to play "information ping-pong" and can help you immediately. + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I am able to reproduce the bug with the [latest version](https://github.com/xdev-software/spring-data-eclipse-store-migration/releases/latest)" + required: true + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/spring-data-eclipse-store-migration/issues) or [closed](https://github.com/xdev-software/spring-data-eclipse-store-migration/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + required: true + - label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise." + required: true + - label: "This issue contains only one bug." + required: true + + - type: input + id: app-version + attributes: + label: Affected version + description: "In which version did you encounter the bug?" + placeholder: "x.x.x" + validations: + required: true + + - type: textarea + id: steps-to-reproduce + attributes: + label: Steps to reproduce the bug + description: | + What did you do for the bug to show up? + + If you can't cause the bug to show up again reliably (and hence don't have a proper set of steps to give us), please still try to give as many details as possible on how you think you encountered the bug. + placeholder: | + 1. Use '...' + 2. Do '...' + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: | + Tell us what you expect to happen. + + - type: textarea + id: actual-behavior + attributes: + label: Actual behavior + description: | + Tell us what happens with the steps given above. + + - type: textarea + id: additional-information + attributes: + label: Additional information + description: | + Any other relevant information you'd like to include diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..b6fb79b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: 💬 Contact support + url: https://xdev.software/en/services/support + about: "If you need support as soon as possible or/and you can't wait for any pull request" diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml new file mode 100644 index 0000000..30e0c71 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -0,0 +1,33 @@ +name: ✨ Feature/Enhancement +description: Suggest a new feature or enhancement +labels: [enhancement] +type: feature +body: + - type: markdown + attributes: + value: | + Thank you for suggesting a new feature/enhancement. + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/spring-data-eclipse-store-migration/issues) or [closed](https://github.com/xdev-software/spring-data-eclipse-store-migration/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + required: true + - label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise." + required: true + - label: "This issue contains only one feature request/enhancement." + required: true + + - type: textarea + id: description + attributes: + label: Description + validations: + required: true + + - type: textarea + id: additional-information + attributes: + label: Additional information diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..7a409b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,31 @@ +name: ❓ Question +description: Ask a question +labels: [question] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this form! + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/spring-data-eclipse-store-migration/issues) or [closed](https://github.com/xdev-software/spring-data-eclipse-store-migration/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + required: true + - label: "I have taken the time to fill in all the required details. I understand that the question will be dismissed otherwise." + required: true + + - type: textarea + id: what-is-the-question + attributes: + label: What is/are your question(s)? + validations: + required: true + + - type: textarea + id: additional-information + attributes: + label: Additional information + description: "Any other information you'd like to include - for instance logs, screenshots, etc." diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 28d6d7b..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: 2 -updates: -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: daily - # Run it at a specific time so that we don't get emails all day long - time: "00:00" - open-pull-requests-limit: 10 - ignore: - - dependency-name: "*" - # GitHub actions are using git tags (v1 = v1.2 = v1.2.3) which should be compatible until a major change is performed - update-types: - - "version-update:semver-minor" - - "version-update:semver-patch" -- package-ecosystem: maven - directory: "/" - schedule: - interval: daily - # Run it at a specific time so that we don't get emails all day long - time: "00:00" - open-pull-requests-limit: 10 diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..325f4ce --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,38 @@ +# Default +## Required for template +- name: bug + description: "Something isn't working" + color: 'd73a4a' +- name: enhancement + description: New feature or request + color: '#a2eeef' +- name: question + description: Information is requested + color: '#d876e3' +## Others +- name: duplicate + description: This already exists + color: '#cfd3d7' +- name: good first issue + description: Good for newcomers + color: '#7057ff' +- name: help wanted + description: Extra attention is needed + color: '#008672' +- name: invalid + description: "This doesn't seem right" + color: '#e4e669' +# Custom +- name: automated + description: Created by an automation + color: '#000000' +- name: "can't reproduce" + color: '#e95f2c' +- name: customer-requested + description: Was requested by a customer of us + color: '#068374' +- name: stale + color: '#ededed' +- name: waiting-for-response + description: If no response is received after a certain time the issue will be closed + color: '#202020' diff --git a/.github/workflows/broken-links.yml b/.github/workflows/broken-links.yml new file mode 100644 index 0000000..16a3f37 --- /dev/null +++ b/.github/workflows/broken-links.yml @@ -0,0 +1,46 @@ +name: Broken links + +on: + workflow_dispatch: + schedule: + - cron: "23 23 * * 0" + +permissions: + issues: write + +jobs: + link-checker: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + + - run: mv .github/.lycheeignore .lycheeignore + + - name: Link Checker + id: lychee + uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2 + with: + fail: false # Don't fail on broken links, create an issue instead + + - name: Find already existing issue + id: find-issue + run: | + echo "number=$(gh issue list -l 'bug' -l 'automated' -L 1 -S 'in:title \"Link Checker Report\"' -s 'open' --json 'number' --jq '.[].number')" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ github.token }} + + - name: Close issue if everything is fine + if: env.lychee_exit_code == 0 && steps.find-issue.outputs.number != '' + run: gh issue close -r 'not planned' ${{ steps.find-issue.outputs.number }} + env: + GH_TOKEN: ${{ github.token }} + + - name: Create Issue From File + if: env.lychee_exit_code != 0 + uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd # v5 + with: + issue-number: ${{ steps.find-issue.outputs.number }} + title: Link Checker Report + content-filepath: ./lychee/out.md + labels: bug, automated diff --git a/.github/workflows/checkBuild.yml b/.github/workflows/check-build.yml similarity index 58% rename from .github/workflows/checkBuild.yml rename to .github/workflows/check-build.yml index 83c8056..1403b41 100644 --- a/.github/workflows/checkBuild.yml +++ b/.github/workflows/check-build.yml @@ -7,6 +7,7 @@ on: paths-ignore: - '**.md' - '.config/**' + - '.github/**' - '.idea/**' - 'assets/**' pull_request: @@ -14,15 +15,14 @@ on: paths-ignore: - '**.md' - '.config/**' + - '.github/**' - '.idea/**' - 'assets/**' -env: - PRIMARY_MAVEN_MODULE: ${{ github.event.repository.name }} - jobs: build: runs-on: ubuntu-latest + timeout-minutes: 30 strategy: matrix: @@ -40,7 +40,7 @@ jobs: cache: 'maven' - name: Build with Maven - run: mvn -B clean package + run: ./mvnw -B clean package - name: Check for uncommited changes run: | @@ -56,12 +56,14 @@ jobs: echo ---------------------------------------- echo Troubleshooting echo ---------------------------------------- - echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && mvn -B clean package" + echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && ./mvnw -B clean package" exit 1 fi - code-style: + checkstyle: runs-on: ubuntu-latest + if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/') }} + timeout-minutes: 15 strategy: matrix: @@ -79,4 +81,39 @@ jobs: cache: 'maven' - name: Run Checkstyle - run: mvn -B checkstyle:check -P checkstyle -T2C + run: ./mvnw -B checkstyle:check -P checkstyle -T2C + + pmd: + runs-on: ubuntu-latest + if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/') }} + timeout-minutes: 15 + + strategy: + matrix: + java: [17] + distribution: [temurin] + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: ${{ matrix.distribution }} + java-version: ${{ matrix.java }} + cache: 'maven' + + - name: Run PMD + run: ./mvnw -B test pmd:aggregate-pmd-no-fork pmd:check -P pmd -DskipTests -T2C + + - name: Run CPD (Copy Paste Detector) + run: ./mvnw -B pmd:aggregate-cpd pmd:cpd-check -P pmd -DskipTests -T2C + + - name: Upload report + if: always() + uses: actions/upload-artifact@v4 + with: + name: pmd-report + if-no-files-found: ignore + path: | + target/reports/** diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 41e648f..002fb9d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,8 +12,9 @@ permissions: pull-requests: write jobs: - check_code: # Validates the code + check-code: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v4 @@ -25,7 +26,7 @@ jobs: cache: 'maven' - name: Build with Maven - run: mvn -B clean package + run: ./mvnw -B clean package -T2C - name: Check for uncommited changes run: | @@ -41,13 +42,14 @@ jobs: echo ---------------------------------------- echo Troubleshooting echo ---------------------------------------- - echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && mvn -B clean package" + echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && ./mvnw -B clean package" exit 1 fi - prepare_release: + prepare-release: runs-on: ubuntu-latest - needs: [check_code] + needs: [check-code] + timeout-minutes: 10 outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: @@ -60,18 +62,19 @@ jobs: - name: Un-SNAP run: | + mvnwPath=$(readlink -f ./mvnw) modules=("") # root - modules+=($(grep -ozP '(?<=module>)[^<]+' 'pom.xml' | tr -d '\0')) + modules+=($(grep -oP '(?<=)[^<]+' 'pom.xml')) for i in "${modules[@]}" do echo "Processing $i/pom.xml" - (cd "$i" && mvn -B versions:set -DremoveSnapshot -DgenerateBackupPoms=false) + (cd "$i" && $mvnwPath -B versions:set -DremoveSnapshot -DgenerateBackupPoms=false) done - name: Get version id: version run: | - version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + version=$(../mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) echo "release=$version" >> $GITHUB_OUTPUT echo "releasenumber=${version//[!0-9]/}" >> $GITHUB_OUTPUT working-directory: ${{ env.PRIMARY_MAVEN_MODULE }} @@ -86,14 +89,14 @@ jobs: - name: Create Release id: create_release - uses: shogo82148/actions-create-release@v1 + uses: shogo82148/actions-create-release@e5f206451d4ace2da9916d01f1aef279997f8659 # v1 with: tag_name: v${{ steps.version.outputs.release }} release_name: v${{ steps.version.outputs.release }} commitish: master body: | - ## [Changelog](https://github.com/xdev-software/${{ env.PRIMARY_MAVEN_MODULE }}/blob/develop/CHANGELOG.md#${{ steps.version.outputs.releasenumber }}) - See [Changelog#v${{ steps.version.outputs.release }}](https://github.com/xdev-software/${{ env.PRIMARY_MAVEN_MODULE }}/blob/develop/CHANGELOG.md#${{ steps.version.outputs.releasenumber }}) for more information. + ## [Changelog](https://github.com/${{ github.repository }}/blob/develop/CHANGELOG.md#${{ steps.version.outputs.releasenumber }}) + See [Changelog#v${{ steps.version.outputs.release }}](https://github.com/${{ github.repository }}/blob/develop/CHANGELOG.md#${{ steps.version.outputs.releasenumber }}) for more information. ## Usage Execute the following maven command in the maven project that you want to migrate: @@ -103,9 +106,10 @@ jobs: -Drewrite.activeRecipes=software.xdev.spring.data.eclipse.store.JpaMigration ``` - publish_central: # Publish the code to central + publish-maven: runs-on: ubuntu-latest - needs: [prepare_release] + needs: [prepare-release] + timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -115,29 +119,29 @@ jobs: git config --global user.name "GitHub Actions" git pull - - name: Set up JDK Apache Maven Central + - name: Set up JDK uses: actions/setup-java@v4 with: # running setup-java again overwrites the settings.xml java-version: '17' distribution: 'temurin' - server-id: ossrh + server-id: sonatype-central-portal server-username: MAVEN_CENTRAL_USERNAME server-password: MAVEN_CENTRAL_TOKEN gpg-passphrase: MAVEN_GPG_PASSPHRASE gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - - name: Publish to Apache Maven Central - run: mvn -B deploy -Possrh + - name: Publish to Central Portal + run: ../mvnw -B deploy -P publish-sonatype-central-portal -DskipTests env: - MAVEN_CENTRAL_USERNAME: ${{ secrets.S01_OSS_SONATYPE_MAVEN_USERNAME }} - MAVEN_CENTRAL_TOKEN: ${{ secrets.S01_OSS_SONATYPE_MAVEN_TOKEN }} + MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_MAVEN_CENTRAL_PORTAL_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_MAVEN_CENTRAL_PORTAL_TOKEN }} MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} working-directory: ${{ env.PRIMARY_MAVEN_MODULE }} publish-pages: - name: Publish dependencies and licenses to github pages runs-on: ubuntu-latest - needs: [prepare_release] + needs: [prepare-release] + timeout-minutes: 15 steps: - uses: actions/checkout@v4 @@ -154,44 +158,21 @@ jobs: distribution: 'temurin' cache: 'maven' - - name: Build dependencies/licenses files - run: mvn -B project-info-reports:dependencies + - name: Build site + run: ../mvnw -B compile site -DskipTests -T2C working-directory: ${{ env.PRIMARY_MAVEN_MODULE }} - - name: Upload licenses - Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: dependencies-licenses - path: ${{ env.PRIMARY_MAVEN_MODULE }}/target/site - - - name: Generate docs/dependencies dir - run: mkdir -p docs/dependencies - - - name: Move built files into docs/dependencies - run: mv ${{ env.PRIMARY_MAVEN_MODULE }}/target/site/* docs/dependencies - - - name: Rename dependencies.html to index.html - working-directory: docs/dependencies - run: mv dependencies.html index.html - - - name: Copy Readme into docs (as index.md) - run: cp README.md docs/index.md - - - name: Configure Pages - working-directory: docs - run: |- - echo "theme: jekyll-theme-tactile" > _config.yml - - name: Deploy to Github pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs - enable_jekyll: true + publish_dir: ./${{ env.PRIMARY_MAVEN_MODULE }}/target/site + force_orphan: true - after_release: + after-release: runs-on: ubuntu-latest - needs: [publish_central] + needs: [publish-maven] + timeout-minutes: 10 steps: - uses: actions/checkout@v4 @@ -203,12 +184,13 @@ jobs: - name: Inc Version and SNAP run: | + mvnwPath=$(readlink -f ./mvnw) modules=("") # root - modules+=($(grep -ozP '(?<=module>)[^<]+' 'pom.xml' | tr -d '\0')) + modules+=($(grep -oP '(?<=)[^<]+' 'pom.xml')) for i in "${modules[@]}" do echo "Processing $i/pom.xml" - (cd "$i" && mvn -B build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion} -DgenerateBackupPoms=false -DnextSnapshot=true) + (cd "$i" && $mvnwPath -B build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion} -DgenerateBackupPoms=false -DnextSnapshot=true -DupdateMatchingVersions=false) done - name: Git Commit and Push diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index bd37fc9..df6dbb7 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -7,13 +7,15 @@ on: paths-ignore: - '**.md' - '.config/**' + - '.github/**' - '.idea/**' - 'assets/**' pull_request: - types: [opened, synchronize, reopened] + branches: [ develop ] paths-ignore: - '**.md' - '.config/**' + - '.github/**' - '.idea/**' - 'assets/**' @@ -22,11 +24,24 @@ env: SONARCLOUD_HOST: https://sonarcloud.io jobs: - sonar: - name: SonarCloud Scan + token-check: + runs-on: ubuntu-latest + if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'renovate/')) }} + timeout-minutes: 5 + outputs: + hasToken: ${{ steps.check-token.outputs.has }} + steps: + - id: check-token + run: | + [ -z $SONAR_TOKEN ] && echo "has=false" || echo "has=true" >> "$GITHUB_OUTPUT" + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + sonar-scan: runs-on: ubuntu-latest - # Dependabot PRs have no access to secrets (SONAR_TOKEN) -> Ignore them - if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'dependabot/') }} + needs: token-check + if: ${{ needs.token-check.outputs.hasToken }} + timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: @@ -54,7 +69,7 @@ jobs: - name: Build with Maven run: | - mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + ./mvnw -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ -DskipTests \ -Dsonar.projectKey=${{ env.SONARCLOUD_ORG }}_${{ github.event.repository.name }} \ -Dsonar.organization=${{ env.SONARCLOUD_ORG }} \ diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..dc67287 --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,25 @@ +name: Sync labels + +on: + push: + branches: develop + paths: + - .github/labels.yml + + workflow_dispatch: + +permissions: + issues: write + +jobs: + labels: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + sparse-checkout: .github/labels.yml + + - uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2 + with: + config-file: .github/labels.yml diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index 4e883f8..8a85891 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -7,26 +7,27 @@ env: PRIMARY_MAVEN_MODULE: ${{ github.event.repository.name }} jobs: - publish_central: # Publish the code to central + publish-maven: runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v4 - - name: Set up JDK OSSRH + - name: Set up JDK uses: actions/setup-java@v4 with: # running setup-java again overwrites the settings.xml distribution: 'temurin' java-version: '17' - server-id: ossrh + server-id: sonatype-central-portal server-username: MAVEN_CENTRAL_USERNAME server-password: MAVEN_CENTRAL_TOKEN gpg-passphrase: MAVEN_GPG_PASSPHRASE gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - - name: Publish to OSSRH - run: mvn -B deploy -Possrh + - name: Publish to Central Portal + run: ../mvnw -B deploy -P publish-sonatype-central-portal -DskipTests working-directory: ${{ env.PRIMARY_MAVEN_MODULE }} env: - MAVEN_CENTRAL_USERNAME: ${{ secrets.S01_OSS_SONATYPE_MAVEN_USERNAME }} - MAVEN_CENTRAL_TOKEN: ${{ secrets.S01_OSS_SONATYPE_MAVEN_TOKEN }} + MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_MAVEN_CENTRAL_PORTAL_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_MAVEN_CENTRAL_PORTAL_TOKEN }} MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index a325e2b..65f56b0 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -1,9 +1,10 @@ name: Update from Template # This workflow keeps the repo up to date with changes from the template repo (REMOTE_URL) -# It duplicates the REMOTE_BRANCH (into UPDATE_BRANCH) and tries to merge it into the +# It duplicates the REMOTE_BRANCH (into UPDATE_BRANCH) and tries to merge it into # this repos default branch (which is checked out here) # Note that this requires a PAT (Personal Access Token) - at best from a servicing account +# PAT permissions: read:discussion, read:org, repo, workflow # Also note that you should have at least once merged the template repo into the current repo manually # otherwise a "refusing to merge unrelated histories" error might occur. @@ -11,9 +12,15 @@ on: schedule: - cron: '55 2 * * 1' workflow_dispatch: + inputs: + no_automatic_merge: + type: boolean + description: 'No automatic merge' + default: false env: UPDATE_BRANCH: update-from-template + UPDATE_BRANCH_MERGED: update-from-template-merged REMOTE_URL: https://github.com/xdev-software/standard-maven-template.git REMOTE_BRANCH: master @@ -24,7 +31,10 @@ permissions: jobs: update: runs-on: ubuntu-latest - + timeout-minutes: 60 + outputs: + update_branch_merged_commit: ${{ steps.manage-branches.outputs.update_branch_merged_commit }} + create_update_branch_merged_pr: ${{ steps.manage-branches.outputs.create_update_branch_merged_pr }} steps: - uses: actions/checkout@v4 with: @@ -36,11 +46,11 @@ jobs: - name: Init Git run: | - git config --global user.email "actions@github.com" - git config --global user.name "GitHub Actions" + git config --global user.email "111048771+xdev-gh-bot@users.noreply.github.com" + git config --global user.name "XDEV Bot" - - name: Main workflow - id: main + - name: Manage branches + id: manage-branches run: | echo "Adding remote template-repo" git remote add template ${{ env.REMOTE_URL }} @@ -48,8 +58,9 @@ jobs: echo "Fetching remote template repo" git fetch template - echo "Deleting local branch that will contain the updates - if present" + echo "Deleting local branches that will contain the updates - if present" git branch -D ${{ env.UPDATE_BRANCH }} || true + git branch -D ${{ env.UPDATE_BRANCH_MERGED }} || true echo "Checking if the remote template repo has new commits" git rev-list ..template/${{ env.REMOTE_BRANCH }} @@ -57,10 +68,12 @@ jobs: if [ $(git rev-list --count ..template/${{ env.REMOTE_BRANCH }}) -eq 0 ]; then echo "There are no commits new commits on the template repo" - echo "Deleting origin branch that contains the updates - if present" + echo "Deleting origin branch(es) that contain the updates - if present" git push -f origin --delete ${{ env.UPDATE_BRANCH }} || true + git push -f origin --delete ${{ env.UPDATE_BRANCH_MERGED }} || true - echo "abort=1" >> $GITHUB_OUTPUT + echo "create_update_branch_pr=0" >> $GITHUB_OUTPUT + echo "create_update_branch_merged_pr=0" >> $GITHUB_OUTPUT exit 0 fi @@ -73,21 +86,235 @@ jobs: echo "Pushing update branch" git push -f -u origin ${{ env.UPDATE_BRANCH }} - echo "Getting current branch" - current_branch=$(git branch --show-current) - echo "Current branch is $current_branch" - echo "current_branch=$current_branch" >> $GITHUB_OUTPUT + echo "Getting base branch" + base_branch=$(git branch --show-current) + echo "Base branch is $base_branch" + echo "base_branch=$base_branch" >> $GITHUB_OUTPUT - echo "abort=0" >> $GITHUB_OUTPUT + echo "Trying to create auto-merged branch ${{ env.UPDATE_BRANCH_MERGED }}" + git branch ${{ env.UPDATE_BRANCH_MERGED }} ${{ env.UPDATE_BRANCH }} + git checkout ${{ env.UPDATE_BRANCH_MERGED }} - - name: pull-request - if: steps.main.outputs.abort == 0 + echo "Merging branch $base_branch into ${{ env.UPDATE_BRANCH_MERGED }}" + git merge $base_branch && merge_exit_code=$? || merge_exit_code=$? + if [ $merge_exit_code -ne 0 ]; then + echo "Auto merge failed! Manual merge required" + echo "::notice ::Auto merge failed - Manual merge required" + + echo "Cleaning up failed merge" + git merge --abort + git checkout $base_branch + git branch -D ${{ env.UPDATE_BRANCH_MERGED }} || true + + echo "Deleting auto-merge branch - if present" + git push -f origin --delete ${{ env.UPDATE_BRANCH_MERGED }} || true + + echo "create_update_branch_pr=1" >> $GITHUB_OUTPUT + echo "create_update_branch_merged_pr=0" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "Post processing: Trying to automatically fill in template variables" + find . -type f \ + -not -path "./.git/**" \ + -not -path "./.github/workflows/update-from-template.yml" -print0 \ + | xargs -0 sed -i "s/template-placeholder/${GITHUB_REPOSITORY#*/}/g" + + git status + git add --all + + if [[ "$(git status --porcelain)" != "" ]]; then + echo "Filled in template; Committing" + + git commit -m "Fill in template" + fi + + echo "Pushing auto-merged branch" + git push -f -u origin ${{ env.UPDATE_BRANCH_MERGED }} + + echo "update_branch_merged_commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + echo "Restoring base branch $base_branch" + git checkout $base_branch + + echo "create_update_branch_pr=0" >> $GITHUB_OUTPUT + echo "create_update_branch_merged_pr=1" >> $GITHUB_OUTPUT + echo "try_close_update_branch_pr=1" >> $GITHUB_OUTPUT + + - name: Create/Update PR update_branch + if: steps.manage-branches.outputs.create_update_branch_pr == 1 env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} run: | gh_pr_up() { gh pr create -H "${{ env.UPDATE_BRANCH }}" "$@" || (git checkout "${{ env.UPDATE_BRANCH }}" && gh pr edit "$@") } - gh_pr_up -B "${{ steps.main.outputs.current_branch }}" \ + gh_pr_up -B "${{ steps.manage-branches.outputs.base_branch }}" \ --title "Update from template" \ --body "An automated PR to sync changes from the template into this repo" + + # Ensure that only a single PR is open (otherwise confusion and spam) + - name: Close PR update_branch + if: steps.manage-branches.outputs.try_close_update_branch_pr == 1 + env: + GH_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} + run: | + gh pr close "${{ env.UPDATE_BRANCH }}" || true + + - name: Create/Update PR update_branch_merged + if: steps.manage-branches.outputs.create_update_branch_merged_pr == 1 + env: + GH_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} + run: | + gh_pr_up() { + gh pr create -H "${{ env.UPDATE_BRANCH_MERGED }}" "$@" || (git checkout "${{ env.UPDATE_BRANCH_MERGED }}" && gh pr edit "$@") + } + gh_pr_up -B "${{ steps.manage-branches.outputs.base_branch }}" \ + --title "Update from template (auto-merged)" \ + --body "An automated PR to sync changes from the template into this repo" + + # Wait a moment so that checks of PR have higher prio than following job + sleep 3 + + # Split into two jobs to help with executor starvation + auto-merge: + needs: [update] + if: needs.update.outputs.create_update_branch_merged_pr == 1 + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + with: + # Required because otherwise there are always changes detected when executing diff/rev-list + fetch-depth: 0 + # If no PAT is used the following error occurs on a push: + # refusing to allow a GitHub App to create or update workflow `.github/workflows/xxx.yml` without `workflows` permission + token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} + + - name: Init Git + run: | + git config --global user.email "111048771+xdev-gh-bot@users.noreply.github.com" + git config --global user.name "XDEV Bot" + + - name: Checking if auto-merge for PR update_branch_merged can be done + id: auto-merge-check + env: + GH_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} + run: | + not_failed_conclusion="skipped|neutral|success" + not_relevant_app_slug="dependabot|github-pages|sonarqubecloud" + + echo "Waiting for checks to start..." + sleep 40s + + for i in {1..20}; do + echo "Checking if PR can be auto-merged. Try: $i" + + echo "Checking if update-branch-merged exists" + git fetch + if [[ $(git ls-remote --heads origin refs/heads/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + echo "Branch still exists; Continuing..." + else + echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" + exit 0 + fi + + echo "Fetching checks" + cs_response=$(curl -sL \ + --fail-with-body \ + --connect-timeout 60 \ + --max-time 120 \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $GH_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/commits/${{ needs.update.outputs.update_branch_merged_commit }}/check-suites) + + cs_data=$(echo $cs_response | jq '.check_suites[] | { conclusion: .conclusion, slug: .app.slug, check_runs_url: .check_runs_url }') + echo $cs_data + + if [[ -z "$cs_data" ]]; then + echo "No check suite data - Assuming that there are no checks to run" + + echo "perform=1" >> $GITHUB_OUTPUT + exit 0 + fi + + cs_failed=$(echo $cs_data | jq --arg x "$not_failed_conclusion" 'select ((.conclusion == null or (.conclusion | test($x))) | not)') + if [[ -z "$cs_failed" ]]; then + echo "No check failed so far; Checking if relevant checks are still running" + + cs_relevant_still_running=$(echo $cs_data | jq --arg x "$not_relevant_app_slug" 'select (.conclusion == null and (.slug | test($x) | not))') + if [[ -z $cs_relevant_still_running ]]; then + echo "All relevant checks finished - PR can be merged" + + echo "perform=1" >> $GITHUB_OUTPUT + exit 0 + else + echo "Relevant checks are still running" + echo $cs_relevant_still_running + fi + else + echo "Detected failed check" + echo $cs_failed + + echo "perform=0" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "Waiting before next run..." + sleep 30s + done + + echo "Timed out - Assuming executor starvation - Forcing merge" + echo "perform=1" >> $GITHUB_OUTPUT + + - name: Auto-merge update_branch_merged + if: steps.auto-merge-check.outputs.perform == 1 + run: | + echo "Getting base branch" + base_branch=$(git branch --show-current) + echo "Base branch is $base_branch" + + echo "Fetching..." + git fetch + if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + echo "Branch still exists; Continuing..." + else + echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" + exit 0 + fi + + expected_commit="${{ needs.update.outputs.update_branch_merged_commit }}" + actual_commit=$(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) + if [[ "$expected_commit" != "$actual_commit" ]]; then + echo "Branch ${{ env.UPDATE_BRANCH_MERGED }} contains unexpected commit $actual_commit" + echo "Expected: $expected_commit" + + exit 0 + fi + + echo "Ensuring that current branch $base_branch is up-to-date" + git pull + + echo "Merging origin/${{ env.UPDATE_BRANCH_MERGED }} into $base_branch" + git merge origin/${{ env.UPDATE_BRANCH_MERGED }} && merge_exit_code=$? || merge_exit_code=$? + if [ $merge_exit_code -ne 0 ]; then + echo "Unexpected merge failure $merge_exit_code - Requires manual resolution" + + exit 0 + fi + + if [[ "${{ inputs.no_automatic_merge }}" == "true" ]]; then + echo "Exiting due no_automatic_merge" + + exit 0 + fi + + echo "Pushing" + git push + + echo "Cleaning up" + git branch -D ${{ env.UPDATE_BRANCH }} || true + git branch -D ${{ env.UPDATE_BRANCH_MERGED }} || true + git push -f origin --delete ${{ env.UPDATE_BRANCH }} || true + git push -f origin --delete ${{ env.UPDATE_BRANCH_MERGED }} || true diff --git a/.gitignore b/.gitignore index d0e81bf..5c85054 100644 --- a/.gitignore +++ b/.gitignore @@ -39,11 +39,6 @@ buildNumber.properties # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* - -# bin / compiled stuff -target/ - - # JRebel **/resources/rebel.xml **/resources/rebel-remote.xml @@ -76,6 +71,7 @@ target/ .idea/* !.idea/saveactions_settings.xml !.idea/checkstyle-idea.xml +!.idea/externalDependencies.xml !.idea/inspectionProfiles/ .idea/inspectionProfiles/* diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml index 9a5d4ff..b52c3e2 100644 --- a/.idea/checkstyle-idea.xml +++ b/.idea/checkstyle-idea.xml @@ -1,7 +1,7 @@ - 10.12.5 + 10.21.0 JavaOnlyWithTests true true @@ -17,4 +17,4 @@ - + \ No newline at end of file diff --git a/.idea/externalDependencies.xml b/.idea/externalDependencies.xml new file mode 100644 index 0000000..78be5b8 --- /dev/null +++ b/.idea/externalDependencies.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/saveactions_settings.xml b/.idea/saveactions_settings.xml index 71a42c4..848c311 100644 --- a/.idea/saveactions_settings.xml +++ b/.idea/saveactions_settings.xml @@ -4,11 +4,11 @@