diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..a3627b5 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,85 @@ +# GitHub Actions Workflow Configuration + +This template contains 2 workflows: +1. `main.yml` - This workflow is triggered on pull requests to the `main`, `master` or `develop` branches OR on pushes to `main`, `master` or `develop` branches. +2. `release.yml` - This workflow is triggered on pushes to `main` or `master` branches. + +## Configuration +For the workflows to run, you need to configure some secrets in your repository settings as well as make some string replacements in the workflow files. + +### Environment Variables +In `release.yml`, you need to inspect the environment variable definitions and insert your own values for Godot Asset Lib and Itch.io, respectively. + +### String Replacements +In both `main.yml` and `release.yml`, you need to replace, just with the rest of this template repository, replace all occurrences of `ADDON_NAME` with the name of your addon! Please make sure there are no spaces, and only alphanumeric values, dashes and underscores in this sting!. + +### Secrets +#### PAT +Because we're committing back from the workflow to the repo, you need to provide a "Personal Access Token" or "PAT" to the workflow. This is a token that allows the workflow to commit back to the repo. You can create a PAT in your GitHub settings. [See the documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). +This PAT needs to have the `repo` scope. + +Once you have created this PAT, you need to add it to the repository secrets as `PAT`. + +##### Why not use `GITHUB_TOKEN`? +`GITHUB_TOKEN` does not allow commits back to the same repo for security reasons. Hence, we need this specific PAT to allow committing back. + +#### Godot Asset Library +If you want to publish to the Godot Asset Library, you need to add the following secrets to your repository: + +* `ASSET_LIB_PASSWORD` - The password for your Godot Asset Library account + +#### Itch.io +If you want to publish to Itch.io, you need to add the following secrets to your repository: + +* `ITCHIO_SECRET` - This is the secret key for your Itch.io page. You can find it in your addon's settings on Itch.io. + +There are more options to this. Please check out the [respective action's documentation](https://github.com/KikimoraGames/itch-publish). + + + +## How does it work? +### `main.yml` +This is the main workflow that runs on pull requests and pushes to the `main`, `master` or `develop` branches. It just does a shallow git checkout (the latest revision) and runs GUT tests. + + +### `release.yml` +This workflow is triggered on pushes to `main` or `master` branches. It does a full git checkout (all revisions). +It is self-recursive! + +#### First Run +In the first run, it will run the `prerelease` job, which will determine if and how to bump the version. +If there is a version bump determined, it will +* generate and update `CHANGELOG.md` (or create it, if it does not exist) +* update `plugin.cfg` with the new version +* Commit the changes back to the branch + +#### Second Run +On the second run, it will skip the `prerelease` job and run the `release` job instead. +This will: + +* Tag the release commit +* Upload a release artifact for later use +* Create a GitHub release, with the changelog as the release notes + +Once the release job was run, the workflow will then run two other jobs to publish to Itch.io and the Godot Asset Library. + + +## How to do a version bump? +`release.yml` will automatically determine if and how to bump the version using the [Git Hub Action `mathieudutour/github-tag-action`](https://github.com/marketplace/actions/github-tag). It will do this by looking at the commit messages of the commits that are on the branch. + +If you look closely, `release.yml` defines the keywords that are used to determine the version bump with the `custom_release_rules`, but these are in addition to the default Angular Commit Message Convention (see below). The pattern is always: + + ``` + :: + ``` + +where `release_type` is one of ``major``, ``minor`` or ``patch`` and `changelog_section` is a free-form string, which defines a header in the `CHANGELOG.md`. If left empty, it defaults to the Angular defaults. See [Angular Commit Message Convention for more info](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular) + +### Examples + +Appears under "Performance Improvements" header, and under "Breaking Changes" with the breaking change explanation: +``` +perf: pooled HTTP connections + +BREAKING CHANGE: Removed legacy ClientAPI +``` diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..ede28f6 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,72 @@ +name: CI + +# Controls when the workflow will run +on: + push: + branches: + - develop + - main + - master + pull_request: + types: [opened, synchronize, reopened, closed] + branches: + - develop + - main + - master + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + ## Sets environment variable + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + # Run Godot Tests with GUT (https://github.com/bitwes/Gut) + - uses: croconut/godot-tester@v2.5 + with: + # required - you could also use 3.4.4 to run GUT tests with this Godot version + version: "3.5" + # the type of release of godot that the tests should be run with + release_type: "stable" + is-mono: "false" + # the folder with your projects.godot file in it + path: "." + # how long to spend importing assets before tests are run + import-time: "1" + # how long tests can run in seconds + test-timeout: "45" + # the ratio of tests that must pass for this action to pass + # e.g. 0.6 means 60% of your tests must pass + minimum-pass: "1.0" + # the directory containing Gut tests + test-dir: "res://addons/ADDON_NAME/test" + # instead of running GUT's command line tool, you can run a GUT test scene if you have one + # set up correctly + # helps enable things like mouse mocking and current scene to work without any extra coding steps + # set up a scene like in this repo --> located at /tester/test/alt_mode/tests.tscn + # set up a script like in this repo --> located at /tester/test/alt_mode/cli_plugin.gd + # ensure cli_plugin.gd inherits from the GUT plugin + # and exits on test completion + # ensure tests.tscn uses your modified plugin script and check yes for run on load + # uses relative path from your godot project directory + #direct-scene: "test/alt_mode/tests.tscn" + # default is false, set true to count asserts instead of tests + assert-check: "true" + # not checked by default, set to a number to limit the + # maximum amount of failed tests for a passing test suite + max-fails: 0 + # to ensure all SCRIPT ERRORs dont contribute to your failure rate + ignore-errors: "true" + # default is GUTs default: 'res://.gutconfig.json'; set this to load a different config file + config-file: "res://.gutconfig.json" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4d40436 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,167 @@ +name: Release + +on: + push: + branches: + - 'main' + - 'master' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + ITCH_USERNAME: ADDON_NAME_ITCH_USER_NAME + ITCH_GAME_ID: ADDON_NAME_ITCH_GAME_ID + ASSET_LIB_USERNAME: ADDON_NAME_ASSET_LIB_USER_NAME + ASSET_LIB_PASSSWORD: ${{ secrets.ASSET_STORE_PASSWORD }} + ASSET_LIB_ASSET_ID: ADDON_NAME_ASSET_LIB_ASSET_ID + +jobs: + prerelease: + if: "github.event.head_commit.message != 'Release preparation: storing Version and Changelog'" + name: Preparing release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.PAT }} + + - name: Calculate version + id: calculate_version + uses: mathieudutour/github-tag-action@v6.0 + with: + tag_prefix: "" + github_token: ${{ secrets.PAT }} + dry_run: true + default_bump: false + custom_release_rules: | + fix:patch:Bug Fixes, + hotfix:patch:Bug Fixes, + feature:minor:Features, + change:minor:Changes, + breaking:major:Breaking Changes, + major:major:Major Changes, + + - name: "Write changelog" + run: | + CHANGELOG="" + if [ -e addons/ADDON_NAME/CHANGELOG.md ] + then + CHANGELOG=$(cat addons/ADDON_NAME/CHANGELOG.md) + fi + echo -e "${{steps.calculate_version.outputs.changelog}}\n\n${CHANGELOG}" > addons/ADDON_NAME/CHANGELOG.md + if: github.ref == 'refs/heads/main' && steps.calculate_version.outputs.new_version != '' + + - name: "Update version in plugin.cfg" + run: | + sed -i -re 's/version=".+$/version="${{ steps.calculate_version.outputs.new_version }}"/gi' addons/ADDON_NAME/plugin.cfg + if: steps.calculate_version.outputs.new_version != '' + + - name: "Commit" + uses: EndBug/add-and-commit@v7.2.1 + with: + message: 'Release preparation: storing Version and Changelog' + push: true + if: steps.calculate_version.outputs.new_version != '' + + release: + # Create release only after the version was bumped and release notes added: + if: "github.event.head_commit.message == 'Release preparation: storing Version and Changelog'" + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create version + id: create_version + uses: mathieudutour/github-tag-action@v6.0 + with: + tag_prefix: "" + dry_run: ${{ github.ref_name != 'main' }} + github_token: ${{ secrets.GITHUB_TOKEN }} + default_bump: false + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ADDON_NAME-${{ steps.create_version.outputs.new_tag }} + path: addons/ADDON_NAME/ + if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn` + if: steps.create_version.outputs.new_version != '' + + - uses: ncipollo/release-action@v1 + with: + name: ${{ steps.create_version.outputs.new_tag }} + draft: false + prerelease: ${{ github.ref_name != 'main' }} + artifacts: "" + replacesArtifacts: false + generateReleaseNotes: true + token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ steps.create_version.outputs.new_tag }} + if: steps.create_version.outputs.new_version != '' + + itch: + if: "github.ref == 'refs/heads/main' && github.event.head_commit.message == 'Release preparation: storing Version and Changelog'" + runs-on: ubuntu-latest + needs: release + + steps: + + - name: Calculate version + id: calculate_version + uses: mathieudutour/github-tag-action@v6.0 + with: + tag_prefix: "v" + github_token: ${{ secrets.PAT }} + dry_run: true + default_bump: false + + # Using https://github.com/KikimoraGames/itch-publish + - uses: actions/download-artifact@v3 + with: + name: ADDON_NAME-${{ steps.calculate_version.outputs.previous_tag }} + path: addons/ADDON_NAME/ + + - uses: KikimoraGames/itch-publish@v0.0.3 + with: + butlerApiKey: ${{secrets.ITCHIO_SECRET}} + gameData: . + itchUsername: ${{env.ITCH_USERNAME}} + itchGameId: ${{ env.ITCH_GAME_ID }} + buildChannel: windows-mac-linux + buildNumber: ${{ steps.calculate_version.outputs.previous_tag }} + + assetlib: + if: "github.ref == 'refs/heads/main' && github.event.head_commit.message == 'Release preparation: storing Version and Changelog'" + runs-on: ubuntu-latest + needs: release + name: Godot AssetLib + steps: + + - uses: actions/checkout@v3 + + - name: Calculate version + id: calculate_version + uses: mathieudutour/github-tag-action@v6.0 + with: + tag_prefix: "v" + github_token: ${{ secrets.PAT }} + dry_run: true + default_bump: false + + - name: Set Version + run: | + echo "version=${{ steps.calculate_version.outputs.previous_tag }}" >> $GITHUB_ENV + + - name: Godot Asset Lib + uses: deep-entertainment/godot-asset-lib-action@v0.4.0 + with: + username: ${{ env.ASSET_LIB_USERNAME }} + password: ${{ env.ASSET_LIB_PASSSWORD }} + assetId: ${{ env.ASSET_LIB_ASSET_ID }}