Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/actions/setup-godot/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: 'Setup Godot'
description: 'Install Godot binary with caching and optionally install export templates'
inputs:
godot-version:
description: 'Godot version to install (e.g., 4.4.1)'
required: true
install-templates:
description: 'Whether to install export templates'
required: false
default: 'false'

runs:
using: 'composite'
steps:
- name: Cache Godot binary
id: cache-godot
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: /usr/local/bin/godot
key: godot-${{ inputs.godot-version }}-${{ runner.os }}

- name: Install Godot
if: steps.cache-godot.outputs.cache-hit != 'true'
shell: bash
run: |
wget -q https://github.com/godotengine/godot/releases/download/${{ inputs.godot-version }}-stable/Godot_v${{ inputs.godot-version }}-stable_linux.x86_64.zip
unzip -q Godot_v${{ inputs.godot-version }}-stable_linux.x86_64.zip
chmod +x Godot_v${{ inputs.godot-version }}-stable_linux.x86_64
sudo mv Godot_v${{ inputs.godot-version }}-stable_linux.x86_64 /usr/local/bin/godot

- name: Verify Godot installation
shell: bash
run: godot --version

- name: Cache Godot export templates
if: inputs.install-templates == 'true'
id: cache-godot-templates
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.local/share/godot/export_templates/${{ inputs.godot-version }}.stable
key: godot-templates-${{ inputs.godot-version }}-${{ runner.os }}

- name: Install Godot export templates
if: inputs.install-templates == 'true' && steps.cache-godot-templates.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p ~/.local/share/godot/export_templates/${{ inputs.godot-version }}.stable
wget -q https://github.com/godotengine/godot/releases/download/${{ inputs.godot-version }}-stable/Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz
unzip -q Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz
mv templates/* ~/.local/share/godot/export_templates/${{ inputs.godot-version }}.stable/

- name: Verify Godot templates
if: inputs.install-templates == 'true'
shell: bash
run: ls -la ~/.local/share/godot/export_templates/${{ inputs.godot-version }}.stable/
44 changes: 44 additions & 0 deletions .github/actions/test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Test
description: >
Is this commit good. Nothing is packaged for release here and nothing is
published; a failure means the addon is wrong, not that the pipeline is.

A composite action rather than a reusable workflow so it runs in the caller's
job, under the caller's name -- CI / Test, Release / Test -- rather than as a
nested "caller / callee" check.

ONE definition, called by CI and by Release both. Release did not run any of
this before: it read the version, packaged the addon and published it, so the
only thing between a broken commit and the registry was whether somebody
looked at CI first.

A per-repo copy, not a shared action. `uses: ./` is repo-local, so the
fourteen copies of this file are copies -- the accepted cost of no repo's CI
breaking because another repo changed.

runs:
using: composite
steps:
# The addon's own file manifest. Listed rather than globbed: a file dropped
# in a refactor is exactly what this catches, and a glob would happily match
# whatever was left.
- name: Validate addon package
shell: bash
run: |
set -euo pipefail
test -f addon/plugin.cfg

# Godot comes from a LOCAL action, copied from the one castledrop and prizm
# carry. The version used to be a download URL written into ci.yml -- the
# engine this addon is tested against lived in workflow YAML.
- uses: ./.github/actions/setup-godot
with:
godot-version: '4.4.1'

# No `if: hashFiles(...)` guard. This step used to skip itself when
# tests/test.sh was absent, which is indistinguishable from the script being
# renamed or deleted -- a skipped test is a green tick. This addon has a
# suite, so the step runs unconditionally and a missing script now fails.
- name: Godot tests
shell: bash
run: ./tests/test.sh
56 changes: 28 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
name: CI

# Every pull request and every merge to main: test, on one runner.
#
# There is no build. A Godot addon is GDScript in a directory -- what a release
# ships is the same files, zipped -- so the only question is whether it is
# correct, and that is Test's job.
#
# The push trigger is not redundant here: this repository has no CD, so nothing
# else covers a merge to main.
#
# The steps are .github/actions/test, the same definition Release runs. There is
# one of it, and it is the one guarding a publish to the GDAM registry.

on:
pull_request:
push:
branches:
- main
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${ github.ref }
cancel-in-progress: true

jobs:
sanity:
ci:
runs-on: ubuntu-latest
# Bounded, so a step that hangs fails here rather than sitting until the
# runner's own timeout hours later.
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- name: Validate addon package
run: test -f addon/plugin.cfg

- name: Install Godot
if: ${{ hashFiles('tests/test.sh') != '' }}
run: |
set -euo pipefail
curl -fsSL -o /tmp/godot.zip https://github.com/godotengine/godot/releases/download/4.4.1-stable/Godot_v4.4.1-stable_linux.x86_64.zip
unzip -q /tmp/godot.zip -d /tmp/godot
sudo install -m 0755 /tmp/godot/Godot_v4.4.1-stable_linux.x86_64 /usr/local/bin/godot

- name: Run Godot tests
if: ${{ hashFiles('tests/test.sh') != '' }}
run: ./tests/test.sh

- uses: actions/setup-go@v5
if: ${{ hashFiles('cli/go.mod') != '' }}
with:
go-version-file: cli/go.mod
# Third-party actions are pinned by SHA, with the tag in a trailing
# comment so the version is still readable. A tag is a moving reference:
# whoever can move it can run code in this job.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Run Go tests
if: ${{ hashFiles('cli/go.mod') != '' }}
working-directory: cli
run: go test ./...
- name: Test
uses: ./.github/actions/test
13 changes: 12 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ concurrency: release-${{ github.repository }}
jobs:
release:
runs-on: ubuntu-latest
# Bounded, so a step that hangs fails here rather than sitting until the
# runner's own timeout hours later.
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0

Expand Down Expand Up @@ -63,6 +66,14 @@ jobs:
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=$tag" >> "$GITHUB_OUTPUT"

# The same checks CI runs, from the same definition. This workflow used
# to package and publish without running any of them -- the only thing
# between a broken commit and the GDAM registry was whether somebody had
# looked at CI. Running them here against this exact commit is the point:
# CI passing on this SHA earlier is a claim about that run.
- name: Test
uses: ./.github/actions/test

- name: Package addon
run: |
set -euo pipefail
Expand Down
Loading