diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e137574db..61453b754 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,47 +1,203 @@ -# Contributing to Refined Storage +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via +[GitHub issues](https://github.com/refinedmods/refinedstorage/issues), [Discord](https://discordapp.com/invite/VYzsydb), +or any other method with the owners of this repository before making a change. + +## Pull requests + +- Keep your pull request (PR) as small as possible, this makes reviewing easier. +- Commits serve a clear purpose and have a fitting commit message. +- Branches are kept up to date by rebasing (updating a branch by merging makes for a confusing Git history). +- PRs are merged by merging the commits on top of the target branch (which is `develop`). +- Remember to add your changes in `CHANGELOG.md`. If your changes are merely technical, it's not necessary to update the + changelog as it's not relevant for users. + +### Commit messages + +Commit messages must adhere to [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). We +use [Commitlint](https://commitlint.js.org/) to validate commit messages. + +We use +the [conventional configuration](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) +for Commitlint. + +It is recommended to install +the [Conventional Commit plugin](https://plugins.jetbrains.com/plugin/13389-conventional-commit) to make it +easier to write commit messages. + +### Branch names + +Because we use merge commits when merging a PR, branch names will be part of the history of the repository. That is why +branch names must follow a certain standard. + +The format is `{category}/GH-{issue number}/{lowercase-description}` and a branch name can be maximum 50 characters of +length. + +Category must match a +category [used in our Commitlint config](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum). + +Valid examples are: + +- `fix/GH-123/add-branch-linting` +- `docs/GH-123/cleanup` ## Versioning This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Pull requests +### Version metadata -- Keep your PR as small as possible, this makes reviewing easier. -- Commits serve a clear purpose and have a fitting commit message. -- Branches are kept up to date by rebasing, preferably. -- PRs are merged by rebasing the commits on top of the target branch. -- Changes are added in `CHANGELOG.md`. Please refrain from using technical terminology, keep it user-friendly. The - format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +The code doesn't contain version metadata: `build.gradle` specifies a version of `0.0.0` (via Refined Architect). +The versioning information is entirely contained in Git by using tags. + +Per [Semantic Versioning](https://semver.org/spec/v2.0.0.html), the version number being released depends on the changes +in that release. We usually can't predict those +changes at the start of a release cycle, so we can't bump the version at the start of a release cycle. That means that +the version number being released is determined at release time. + +Because the version number is determined at release time, we can't store any versioning metadata in the +code (`build.gradle`). If we did, `build.gradle` would have the version number of the latest released version during the +release cycle of the new version, which isn't correct. + +### Dealing with Minecraft + +Whenever we port to a new Minecraft version, at least the minor version should be incremented. + +This is needed so that we can still support older Minecraft versions without the version numbers conflicting. + +## Changelog + +The changelog is kept in `CHANGELOG.md`. + +Keeping a readable, relevant and user-friendly changelog is essential for our end users +to stay up to date with the project. + +Please refrain from using technical terminology or adding entries for technical changes +that are (generally) not relevant to the end-user. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Gitflow This project uses [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow). -## Releasing +## Documentation -1) Make sure the version number in `build.gradle` is correct. -2) Merge `develop` to `main`. -3) Push a tag with the version number (prefixed with `v`). +Documentation must be kept up to date when adding or changing functionality. -After releasing: +### Javadoc -1) Rename the "Unreleased" section to the correct version number in `CHANGELOG.md`. -2) Upgrade the version number in `build.gradle`. -3) Create a new "Unreleased" section in `CHANGELOG.md`. +Javadoc is available after every release on https://refinedmods.com/refinedstorage/. -## Pipelines +### API annotations + +Public APIs must be annotated with an `@API` annotation +from [API Guardian](https://github.com/apiguardian-team/apiguardian). + +## Code style + +We use [Checkstyle](https://checkstyle.sourceforge.io/) in our build workflow to validate coding style. + +It is recommended to import the [config/checkstyle/checkstyle.xml](../config/checkstyle/checkstyle.xml) file into your +IDE, so that formatting rules are respected. + +Moreover, the [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea) can be used to check +if there are no style violations. + +## Release process + +The release process is automated and follows Gitflow. + +Before running the "Draft release" workflow to start the release process make sure `CHANGELOG.md` contains all the +unreleased changes. + +To determine the version number to be released, the workflow will ask you which release type this is (major, minor, +patch). +The latest version from `CHANGELOG.md` will be used as a base, and that will be incremented +depending on the release type. + +`CHANGELOG.md` will be updated by this workflow, you can review this in the resulting release PR. + +If you merge the release PR, the "Publish release" workflow will automatically publish the release. An additional PR +will be created to merge the changes in `CHANGELOG.md` back into `develop`. + +## Hotfix process + +The hotfix process is semi-automated and follows Gitflow: + +- Create a hotfix branch off `main`. +- Commit your changes on this branch. +- Update `CHANGELOG.md` (with version number and release date) manually on this branch. +- Push the branch and create a PR for it, merging into `main`. + +The "Publish release" workflow will take care of the rest. + +## Workflows + +We have a few GitHub workflows: + +- Build (PRs, pushes to `develop` and `main`) +- Draft release (manual trigger) +- Publish release (merging a PR to `main`) +- Validate changelog (PRs) + - To validate if `CHANGELOG.md` is valid and updated. + - Not every pull request needs a changelog change, so the `skip-changelog` label can be added to the pull request to + ignore this. +- Validate commit messages (PRs) + - Validates whether the commits on a pull request + respect [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). + - We use + the [conventional configuration](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional). +- Validate branch names (PRs) +- Issue for unsupported version (issues) + - Posts a message on a GitHub issue if the issue is about an unsupported version. +- Lock resolved issues and PRs (every night) ### Build -The build pipeline triggers when a commit is pushed to a branch or pull request. +The build workflow triggers when a pull request is updated or when a commit is pushed to `develop` or `main`. -### Release +The build workflow takes care of the following: -The release pipeline triggers when a tag is pushed. This will run all the steps that our build pipeline does. +- Running a Gradle build, running our tests in the process and generating an aggregated code coverage report for the API + modules. +- Analyzing the code on SonarQube. + > Because of + > [limitations with SonarQube](https://portal.productboard.com/sonarsource/1-sonarcloud/c/50-sonarcloud-analyzes-external-pull-request), + > pull requests originating from a fork aren't analyzed on SonarQube. -After that succeeds, it will publish to GitHub packages and CreeperHost Maven repository. +- Code style validation with Checkstyle. +- Mutation and line coverage test with Pitest. +- Uploading the artifacts on the action. -The "Unreleased" section in `CHANGELOG.md` is parsed and a GitHub release is created with the changelog body and -relevant artifacts. +### Draft release -After that, a Discord and Twitter notification is sent. +The draft release workflow is a manual workflow which will create a release branch from `develop`. + +To determine the version number to be released, it will extract the latest version number from `CHANGELOG.md` and +increment it depending on the release type selected. + +This workflow takes care of the following: + +- Creating the release branch. +- Updating the changelog on this release branch. +- Creating a pull request merging the release branch into `main`. + +### Publish release + +The "publish release" workflow is triggered when a release or hotfix PR is merged to `main`. Usually, this will be the +PR created earlier in the "Draft release" workflow. + +The workflow takes care of the following: + +- Extracting the version number from the release or hotfix branch name that is merged in the PR. +- Extracting the changelog entry for this version number. +- Running a build. +- Publishing on [GitHub packages](https://github.com/refinedmods/refinedstorage/packages) and + CreeperHost Maven. +- Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/refinedstorage/tree/gh-pages). +- Deploying on [GitHub releases](https://github.com/refinedmods/refinedstorage/releases). +- Announcing the release on Discord and Twitter. +- Creating a PR that merges `main` back into `develop` to get the changes to `CHANGELOG.md` and `build.gradle` + into `develop` from the draft release workflow. diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 000000000..1f8a2d830 --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,11 @@ +# Support + +If you have a problem and need help, we offer various channels where you can ask for help. + +## I have a question + +Questions can be asked on [Discord](https://discordapp.com/invite/VYzsydb). + +## I have found a bug + +If you have found a bug, please report it on [GitHub issues](https://github.com/refinedmods/refinedstorage/issues). \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 080dd9fb5..7d8ab270e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,44 +1,14 @@ name: Build on: - push: - pull_request: - types: [ opened, synchronize, reopened ] + push: + branches: + - develop + - main + pull_request: + types: [ opened, synchronize, reopened ] jobs: - build: - strategy: - matrix: - java: [ - 17 - ] - os: [ ubuntu-latest ] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 - - name: Setup JDK ${{ matrix.java }} - uses: actions/setup-java@v1 - with: - java-version: ${{ matrix.java }} - - name: Cache Gradle packages - uses: actions/cache@v1 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: ${{ runner.os }}-gradle - - name: Make Gradle wrapper executable - if: ${{ runner.os != 'Windows' }} - run: chmod +x ./gradlew - - name: Build - run: ./gradlew build - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload build artifacts - if: ${{ runner.os == 'Linux' && matrix.java == '17' }} - uses: actions/upload-artifact@v2 - with: - name: Artifacts - path: build/libs/ + build: + uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.5.1 + with: + mutation-testing: false + secrets: inherit diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml new file mode 100644 index 000000000..ac993f467 --- /dev/null +++ b/.github/workflows/draft-release.yml @@ -0,0 +1,24 @@ +name: Draft release +on: + workflow_dispatch: + inputs: + release-type: + description: 'Release type' + required: true + default: 'minor' + type: choice + options: + - major + - minor + - patch + version-number-override: + description: 'Version number override' + required: false + type: string +jobs: + draft: + uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.5.1 + with: + release-type: ${{ inputs.release-type }} + version-number-override: ${{ inputs.version-number-override }} + secrets: inherit diff --git a/.github/workflows/issue-for-unsupported-version.yml b/.github/workflows/issue-for-unsupported-version.yml new file mode 100644 index 000000000..8d3a81155 --- /dev/null +++ b/.github/workflows/issue-for-unsupported-version.yml @@ -0,0 +1,7 @@ +name: Issue for unsupported version +on: + issues: + types: [ labeled, unlabeled, reopened ] +jobs: + unsupported-labeler: + uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.5.1 \ No newline at end of file diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 000000000..aeafe16e6 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,16 @@ +name: Publish release +on: + pull_request: + branches: + - main + types: + - closed +jobs: + publish-release: + uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.5.1 + secrets: inherit + with: + project-name: 'Refined Storage' + announce: true + mutation-testing: false + curseforge: true \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 4eca4ff34..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: Release -on: - push: - tags: - - "v**" -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Get tag name - uses: olegtarasov/get-tag@v2.1 - id: tagName - - name: Validate semver - run: | - echo $GIT_TAG_NAME | grep -oP '^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$' - - name: Checkout repository - uses: actions/checkout@v2 - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 - - name: Setup JDK 17 - uses: actions/setup-java@v1 - with: - java-version: 17 - - name: Make Gradle wrapper executable - if: ${{ runner.os != 'Windows' }} - run: chmod +x ./gradlew - - name: Build - run: ./gradlew build - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RELEASE: ${{ steps.tagName.outputs.tag }} - - name: Build documentation - run: ./gradlew javadoc - env: - RELEASE: ${{ steps.tagName.outputs.tag }} - - name: Publish documentation - uses: JamesIves/github-pages-deploy-action@4.1.5 - with: - branch: gh-pages - folder: build/docs/javadoc - - name: Publish - run: ./gradlew publish - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CREEPERHOST_MAVEN_USERNAME: ${{ secrets.CREEPERHOST_MAVEN_USERNAME }} - CREEPERHOST_MAVEN_TOKEN: ${{ secrets.CREEPERHOST_MAVEN_TOKEN }} - RELEASE: ${{ steps.tagName.outputs.tag }} - - name: Retrieve changelog - id: changelog_reader - uses: mindsers/changelog-reader-action@v2 - with: - version: 'Unreleased' - path: ./CHANGELOG.md - - name: Release on GitHub - uses: softprops/action-gh-release@v1 - id: ghRelease - with: - body: ${{ steps.changelog_reader.outputs.changes }} - name: ${{ steps.tagName.outputs.tag }} - files: | - build/libs/*.jar - - name: Release on CurseForge - run: ./gradlew curseforge - env: - RELEASE: ${{ steps.tagName.outputs.tag }} - CHANGELOG: ${{ steps.changelog_reader.outputs.changes }} - CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }} - # This is necessary because the Discord action doesn't support GH actions variable expansion? - - name: Set release URL - run: | - echo "RELEASE_URL=${{ steps.ghRelease.outputs.url }}" >> $GITHUB_ENV - - name: Notify Discord - uses: Ilshidur/action-discord@0.3.2 - with: - args: 'Refined Storage {{ GIT_TAG_NAME }} has been released! {{ RELEASE_URL }}' - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} - - name: Notify Twitter - uses: ethomson/send-tweet-action@v1 - with: - status: Refined Storage ${{ env.GIT_TAG_NAME }} has been released! ${{ env.RELEASE_URL }} - consumer-key: ${{ secrets.TWITTER_CONSUMER_API_KEY }} - consumer-secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} - access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }} - access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} - - name: Announce to Mastodon - uses: rzr/fediverse-action@master - with: - access-token: ${{ secrets.MASTODON_TOKEN }} - host: 'anvil.social' - message: "Refined Storage ${{ env.GIT_TAG_NAME }} has been released! ${{ env.RELEASE_URL }}" diff --git a/.github/workflows/resolved-issue-locking.yml b/.github/workflows/resolved-issue-locking.yml index 4cbc15d68..f0d141bea 100644 --- a/.github/workflows/resolved-issue-locking.yml +++ b/.github/workflows/resolved-issue-locking.yml @@ -4,10 +4,4 @@ on: - cron: '0 0 * * *' jobs: lock: - runs-on: ubuntu-latest - steps: - - uses: dessant/lock-threads@v2 - with: - github-token: ${{ github.token }} - issue-lock-inactive-days: '30' - pr-lock-inactive-days: '30' \ No newline at end of file + uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.5.1 \ No newline at end of file diff --git a/.github/workflows/unsupported.yml b/.github/workflows/unsupported.yml deleted file mode 100644 index e4a5f4b90..000000000 --- a/.github/workflows/unsupported.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: 'Unsupported versions' -on: - issues: - types: [ labeled, unlabeled, reopened ] -jobs: - support: - runs-on: ubuntu-latest - steps: - - uses: dessant/support-requests@v2 - with: - github-token: ${{ github.token }} - support-label: 'unsupported' - issue-comment: > - :wave: @{issue-author}, we no longer support this version of Minecraft. - Please see https://refinedmods.com/refined-storage/wiki/minecraft-version-support.html - close-issue: true - lock-issue: false diff --git a/.github/workflows/validate-branch-name.yml b/.github/workflows/validate-branch-name.yml new file mode 100644 index 000000000..e7aa38743 --- /dev/null +++ b/.github/workflows/validate-branch-name.yml @@ -0,0 +1,5 @@ +name: Validate branch name +on: [ pull_request ] +jobs: + validate-branch-name: + uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.5.1 \ No newline at end of file diff --git a/.github/workflows/validate-changelog.yml b/.github/workflows/validate-changelog.yml new file mode 100644 index 000000000..8083a0f7f --- /dev/null +++ b/.github/workflows/validate-changelog.yml @@ -0,0 +1,7 @@ +name: Validate changelog +on: + pull_request: + types: [ opened, synchronize, reopened, ready_for_review, labeled, unlabeled ] +jobs: + validate-changelog: + uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.5.1 \ No newline at end of file diff --git a/.github/workflows/validate-commit-messages.yml b/.github/workflows/validate-commit-messages.yml new file mode 100644 index 000000000..d4bfa0e01 --- /dev/null +++ b/.github/workflows/validate-commit-messages.yml @@ -0,0 +1,5 @@ +name: Validate commit messages +on: [ pull_request ] +jobs: + validate-commit-messages: + uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.5.1 \ No newline at end of file diff --git a/README.md b/README.md index 7edaefad1..fa8289c19 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,46 @@ -# Refined Storage [](https://github.com/refinedmods/refinedstorage/actions/workflows/build.yml) [](http://minecraft.curseforge.com/projects/refined-storage) [](https://discordapp.com/invite/VYzsydb) [](LICENSE.md) +
+ Refined Storage is a mass storage mod for Minecraft that offers the player a network-based storage system, allowing +them to store items and fluids on a massively expandable device network.
-**Refined Storage is a mass storage mod for Minecraft that offers the player a network-based storage system, allowing them to store items and fluids on a massively expandable device network.** +[](https://github.com/refinedmods/refinedstorage/actions/workflows/build.yml) [](https://sonarcloud.io/summary/new_code?id=refinedmods_refinedstorage) [](https://sonarcloud.io/summary/new_code?id=refinedmods_refinedstorage) [](https://sonarcloud.io/summary/new_code?id=refinedmods_refinedstorage) [](http://minecraft.curseforge.com/projects/refined-storage) [](https://discordapp.com/invite/VYzsydb) [](LICENSE.md) +