🎬 Godot Rust GitHub Actions
In this Godot Rust CI post, we take a quick look at some GitHub action you might want to add to your project for linting GDScript and Rust code on each commit.
The config, below, is based on the Knights to See You game. I ran through that project and some resources for getting going with Godot Rust bindings in a recent post. You might want to start there if you are new to Rust in Godot.
GitHub actions let you run continuous integration processes on each commit, usually by adding a YAML config file in a .github/workflows
directory for your project. They can take a little trial-and-error to get right, but are worth the effort for keeping code consistent, running unit tests, finding outdated packages and even spotting potential security vulnerabilities.
There is a link further down to the full project code.
🤖 GDScript Linting and Formatting
The project uses a mix of Rust and GDScript, and for linting the GDScript code in GitHub actions, I use godot-gdscript-toolkit.
name: Rust
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
permissions: read-all
# TRUNCATED...
static-checks:
name: 'GDScript Static checks'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: Scony/godot-gdscript-toolkit@9c4fa1cd596149d71e9d867416f3bb7b3a2fed3e # 4.2.2
- run: gdformat --check godot/
- run: gdlint godot/
Setting default read-only permissions in a line 10
is a good idea, to limit access actions have to your repo. You can override this for any actions which require repo write access.
I use commit hashes to identify the exact action I want to run, though you can just use tag, instead.
The project is structured with godot
and rust
folders at the root level, and I set gdformat
and gdlint
only to run on the godot
directory. gdformat
provides opinionated GDScript formatting, while gdlint
includes checks for unnecessary else statements, unused arguments and that your naming is consistent with the GDScript style guide (snake case function names, Pascal Case classes etc) among other checks.
🦀 Rust Linting and Formatting
Rust is well-known for having integrated formatting, linting, testing through cargo utilities, and you can set these up to run in GitHub actions by dtolnay:
name: Rust
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
permissions: read-all
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-Dwarnings -Cinstrument-coverage"
LLVM_PROFILE_FILE: "project-%p-%m.profraw"
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: dtolnay/rust-toolchain@4f366e621dc8fa63f557ca04b8f4361824a35a45 # stable
- name: Run tests
run: cargo test
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: dtolnay/rust-toolchain@4f366e621dc8fa63f557ca04b8f4361824a35a45 # stable
with:
components: rustfmt
- name: Enforce formatting
run: cargo fmt --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: dtolnay/rust-toolchain@4f366e621dc8fa63f557ca04b8f4361824a35a45 # stable
with:
components: clippy
- name: Linting
run: cargo clippy -- -D warnings
You are probably already familiar with these tools, but let me know if the GitHub action side of things needs more explanation.
🧐 Other Handy Rust Actions
Jon Gjengset has a fantastic video, in which he takes you through setting up CI on a Rust GitHub repo. You can clone his setup into any new Rust projects. Essentially, that is the process I followed for Knights to See You. Besides the Rust actions above, I have:
-
msrv check - a check that the project successfully builds using the Minimum Supported Rust version I give in
Cargo.toml
. This is worth checking in CI, since locally you will, likely, be running a newer Rust version. - cargo deny check - this checks the licences of any crates you use in your project and dependencies of those crates. You create your own allow list of licences, and the tool highlights any projects without matching licences. This helps avoid surprises further down the line.
- audit-check - finds crates with security vulnerabilities.
Rust MSRV Check Action
name: Rust
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
permissions: read-all
# TRUNCATED...
msrv:
runs-on: ubuntu-latest
strategy:
matrix:
msrv: ["1.78.0"]
name: ubuntu / ${{ matrix.msrv }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Install Linux Dependencies
run: sudo apt-get update
- name: Install ${{ matrix.msrv }}
uses: dtolnay/rust-toolchain@4f366e621dc8fa63f557ca04b8f4361824a35a45 # stable
with:
toolchain: ${{ matrix.msrv }}
- name: cargo +${{ matrix.msrv }} check
run: cargo check
Cargo Deny Licence Check Action
name: Cargo Deny
on: [push, pull_request]
permissions:
contents: read
jobs:
cargo-deny:
runs-on: ubuntu-22.04
strategy:
matrix:
checks:
- advisories
- bans licenses sources
# Prevent sudden announcement of a new advisory from failing ci:
continue-on-error: ${{ matrix.checks == 'advisories' }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: EmbarkStudios/cargo-deny-action@3f4a782664881cf5725d0ffd23969fcce89fd868 # v1.6.3
with:
command: check ${{ matrix.checks }}
See cargo-deny-action repo for configuration details.
Rust Security Audit Action
name: Security audit
permissions:
contents: read
on:
push:
paths:
- 'Cargo.toml'
- 'Cargo.lock'
jobs:
security_audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: rustsec/audit-check@dd51754d4e59da7395a4cd9b593f0ff2d61a9b95 # v1.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
See audit-check repo for configuration details.
There are more checks you might want to include, depending on your project, and I have only highlighted a few here. See Jon Gjengset’s rust-ci-config repo for more.
🙌🏽 Godot Rust CI: Wrapping Up
In this Godot Rust CI, we took a quick look through some GitHub actions you might want to add to your Godot Rust game. In particular, we looked at:
- actions for linting and formatting GDScript;
- running familiar cargo tooling in GitHub actions; and
- also how to run security audit and licence checks on your Rust crates in CI.
I hope you found this useful. As promised, you can get the full project code on the Rodney Lab GitHub repo. I would love to hear from you, if you are also new to Godot video game development. Were there other resources you found useful? Also, let me know what kind of game you are working on!
🙏🏽 Godot Rust CI: Feedback
If you have found this post useful, see links below for further related content on this site. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on X, giving me a mention, so I can see what you did. Finally, be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please consider supporting me through Buy me a Coffee.
Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on X (previously Twitter) and also, join the #rodney Element Matrix room. Also, see further ways to get in touch with Rodney Lab. I post regularly on Game Dev as well as Rust and C++ (among other topics). Also, subscribe to the newsletter to keep up-to-date with our latest projects.