Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

Red40 reusable GitHub workflows

Reusable GitHub Actions workflows for FiveM projects. Add a small caller workflow to your repository and GitHub will run the implementation from this repository.

The examples below use the v1 release of these workflows. Pin to a commit SHA instead if your repository requires immutable action references.

Available workflows

Workflow Use Required secret
discord-push.yml Send a Discord notification for commits on the default branch DISCORD_WEBHOOK_URL
discord-release.yml Send a Discord changelog when a GitHub release is published DISCORD_WEBHOOK_URL
ci.yml Install dependencies and run pnpm lint, test, and build scripts None
lint.yml Lint a FiveM Lua resource and publish a JUnit check report None by default; optional App credentials
release.yml Prepare a version tag, or build and publish a tagged release None by default; optional App credentials

All workflows are called at the job level with uses:. They are not copied into the consuming repository.

Standalone caller examples are available in examples/.

pnpm CI

Create .github/workflows/ci.yml to run the standard pnpm checks on pushes and pull requests:

name: CI

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

permissions:
  contents: read

jobs:
  ci:
    uses: Red40-Development/red40-public-workflows/.github/workflows/ci.yml@v1

The reusable workflow requires package.json and pnpm-lock.yaml, installs with pnpm install --frozen-lockfile, and runs lint, test, and build when enabled. Missing scripts are skipped. For a project in a subdirectory, set working_directory; node_version, pnpm_version, and the three run_* inputs are also available.

Discord commit notifications

Create .github/workflows/discord-push.yml in your repository:

name: Discord commit notification

on:
  push:
    branches: [main]

jobs:
  notify:
    uses: Red40-Development/red40-public-workflows/.github/workflows/discord-push.yml@v1
    with:
      # Optional. Omit this to use the default Red40 avatar.
      avatar_url: https://example.com/my-avatar.png
    secrets:
      DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}

The reusable workflow also checks that the push is to the repository's configured default branch. Replace main in the caller if your default branch has another name.

Create DISCORD_WEBHOOK_URL under Repository settings → Secrets and variables → Actions. Treat the webhook URL as a password.

Discord release notifications

Create .github/workflows/discord-release.yml:

name: Discord release notification

on:
  release:
    types: [published]

jobs:
  notify:
    uses: Red40-Development/red40-public-workflows/.github/workflows/discord-release.yml@v1
    secrets:
      DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}

Optional inputs are avatar_url, footer_icon_url, footer_title, remove_github_reference_links, and color:

    with:
      avatar_url: https://example.com/my-avatar.png
      footer_icon_url: https://example.com/my-footer-icon.png
      footer_title: "My Development Bot"
      remove_github_reference_links: false
      color: "16736808"

FiveM Lua linting

Create .github/workflows/lint.yml:

name: Lint

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  lint:
    uses: Red40-Development/red40-public-workflows/.github/workflows/lint.yml@v1
    permissions:
      contents: read
      checks: write
    with:
      # Optional. The default is suitable for the standard Red40/Qbox setup.
      extra_libs: ox_lib+mysql+qblocales+qbox+qbox_playerdata+qbox_lib

extra_libs is a +-separated list of additional FiveM resources to make available to the linter. The reusable job is restricted to the default branch, so calls from other refs are skipped.

Release preparation and publishing

The release workflow has two operations:

  1. prepare validates the version, updates fxmanifest.lua, commits the change, and creates an annotated tag.
  2. publish checks out that tag, optionally builds web/, creates a ZIP archive, generates changelog notes, and creates or updates the GitHub release.

Create .github/workflows/release.yml:

name: Release

on:
  workflow_dispatch:
    inputs:
      operation:
        description: Release operation
        required: true
        type: choice
        options:
          - prepare
          - publish
      version:
        description: Release tag, for example v1.2.3
        required: true
        type: string

jobs:
  release:
    uses: Red40-Development/red40-public-workflows/.github/workflows/release.yml@v1
    permissions:
      contents: write
    with:
      operation: ${{ inputs.operation }}
      version: ${{ inputs.version }}

Run prepare first. After it succeeds, run publish with the same version. Versions must start with v, for example v1.2.3, and the repository must contain an fxmanifest.lua with a version directive.

The example above is intentionally manual and works with only GITHUB_TOKEN. If you want prepare to automatically trigger publish when it pushes the version tag, use examples/release-on-tag.yml:

name: Create Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: Release tag (for example, v1.2.3)
        required: true
        type: string
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  release:
    name: ${{ github.event_name == 'workflow_dispatch' && 'Prepare release' || 'Publish release' }}
    uses: Red40-Development/red40-public-workflows/.github/workflows/release.yml@v1
    with:
      operation: ${{ github.event_name == 'workflow_dispatch' && 'prepare' || 'publish' }}
      version: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
    secrets:
      CLIENT_APP_ID: ${{ secrets.CLIENT_APP_ID }}
      PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

This automatic pattern requires the optional GitHub App credentials described below. A tag pushed with GITHUB_TOKEN does not create another Actions run, so without the App the publish phase must be started manually.

By default, the bundle includes files that are not ignored by Git, excludes .github, .git, .vscode, .assets, node_modules, and ZIP files, and includes web/build/ when present. Add a .cfxrelease file to explicitly select files with one glob pattern per line:

fxmanifest.lua
client/**/*.lua
server/**/*.lua
shared/**/*.lua
web/build/**

Optional GitHub App credentials

Lint and release use the caller repository's built-in GITHUB_TOKEN by default. The caller must grant it the permissions shown in the examples: checks: write for lint and contents: write for releases.

You only need a GitHub App when the workflow must access repositories outside the caller repository—for example, private submodules—or when you want a dedicated bot identity for release commits. If you provide both optional secrets, the reusable workflow uses the App token instead of GITHUB_TOKEN.

Create and install the App as follows:

  1. Open Settings → Developer settings → GitHub Apps → New GitHub App. For an organization-owned app, use the organization’s developer settings.
  2. Give the app a name and homepage URL. Webhooks and user authorization are not needed by these workflows, so leave them disabled unless you need them for another purpose.
  3. Under Repository permissions, select:
    • Checks: Read and write for lint.yml.
    • Contents: Read and write for release.yml.
    • If using both workflows, select both permissions.
  4. Create the app. On the app’s settings page, copy the Client ID. This is the value used as CLIENT_APP_ID; it is different from the numeric App ID.
  5. In the app settings, select Generate a private key. GitHub downloads a .pem file. Store its complete contents, including the BEGIN and END lines, as the PRIVATE_KEY Actions secret. Never commit this file.
  6. Select Install App, choose your user or organization, and grant access to the repositories that will use these workflows. Choose Only select repositories when possible.
  7. Add the values to each consuming repository under Settings → Secrets and variables → Actions → Secrets:
    • CLIENT_APP_ID: the Client ID copied in step 4.
    • PRIVATE_KEY: the complete PEM private key from step 5.

Pass those optional secrets to the reusable workflow when needed:

    secrets:
      CLIENT_APP_ID: ${{ secrets.CLIENT_APP_ID }}
      PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

The app must be installed on the repository before a lint or release run. If the release workflow checks out private submodules, install the app on those repositories too. Changes to App permissions may require approving the updated installation again.

Keep the private key secret and rotate it by generating a new key and replacing PRIVATE_KEY if it is exposed. GitHub App installation tokens generated during a run expire after one hour.

Troubleshooting

  • Resource not accessible by integration: confirm the caller grants the required GITHUB_TOKEN permission. If using an App, also confirm its permission, installation scope, and secret names.
  • Lint check creation fails: grant the caller checks: write, or grant the optional App Checks: Read and write permission.
  • Release cannot push a tag or create a release: grant the caller contents: write, or grant the optional App Contents: Read and write permission.
  • The job is skipped: discord-push.yml and lint.yml intentionally run only when the triggering ref is the repository’s default branch.

References

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors