DEV Community

Cover image for Godot Rust CI: Handy GDScript & Rust GitHub Actions
Rodney Lab
Rodney Lab

Posted on • Originally published at rodneylab.com

Godot Rust CI: Handy GDScript & Rust GitHub Actions

🎬 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/
Enter fullscreen mode Exit fullscreen mode

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.

Godot Rust C I: screen capture show log from Git Hub action running godot-g d script-toolkit.  g d format output reads 4 files would be left unchanged and g d lint output reads Success: no problems found.

🦀 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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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 }}
Enter fullscreen mode Exit fullscreen mode

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 }}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)