Welcome! If you're looking to contribute or understand how this project operates under the hood, this guide is for you.
The build and deployment process is fully automated using GitHub Actions.
Every push to the main branch triggers the primary workflow, which consists of three jobs:
- Build: Compiles the Docker image and pushes a temporary staging tag (using the commit SHA) to the GitHub Container Registry (GHCR).
- Test: Pulls the staging image from GHCR and runs end-to-end tests (
scripts/test-startup.sh) to ensure the server starts correctly. - Publish (Only on Release): If the workflow was triggered by a Git semantic version tag (e.g.,
v1.0.0), the tested image is pulled, tagged with the release version andlatest, and pushed to Docker Hub for public consumption.
To release a new version of the image to Docker Hub:
- Ensure all changes are merged into
mainand tests pass. - Create and push a new Git tag:
git tag v1.x.x git push origin v1.x.x
- The pipeline will automatically build, test, and publish the tagged image.
To keep our registries clean, we use a scheduled workflow (.github/workflows/prune-registries.yml) that runs every Sunday.
- GHCR: Deletes any untagged images (which accumulate when staging tags are overwritten).
- Docker Hub: Runs an API script to delete old, commit-SHA tagged images, preserving only
latestand semantic version tags (vX.X.X).
For the automated registry pruning to work, repository secrets must be properly configured:
PAT_WITH_DELETE_PACKAGES_SCOPE: A GitHub Personal Access Token created by an admin with thedelete:packagesscope. The defaultGITHUB_TOKENdoes not have permission to delete packages from GHCR.DOCKERHUB_TOKEN: A Docker Hub Personal Access Token. This token MUST be created with Read, Write, and Delete permissions. If it lacks delete permissions, the script will receive a403 Forbiddenerror when attempting to prune old staging tags.
This project uses custom GitHub Actions to automatically track and propose updates for critical dependencies.
- Wine (
.github/workflows/update-wine.yml): Runs monthly. It queries the Ubuntu Noble WineHQ repository for the latestwinehq-stableversion and proposes a PR to update theWINE_VERSIONin theDockerfile. - V Rising (
.github/workflows/update-vrising.yml): Runs weekly. It queries the SteamCMD Web API for the latestbuildidof the V Rising Dedicated Server and proposes a PR to update theVRISING_BUILD_IDin theDockerfile.
These automated PRs ensure the Docker image stays up-to-date with upstream changes without manual tracking. Merging these PRs will automatically trigger the standard docker-image.yml build pipeline.
This project uses OpenSpec, an experimental artifact-driven workflow, to manage significant changes. This ensures every change is deliberately proposed, designed, and specified before any code is written.
OpenSpec creates a paper trail for the intent and rationale behind code changes. It breaks down complex ideas into manageable, trackable artifacts.
-
Start a New Change: Use the Gemini CLI (or OpenSpec directly) to initialize a new change directory.
/opsx:new add-new-feature
This creates a folder in
openspec/changes/add-new-feature/. -
Artifact Sequence: You will be guided to create a series of Markdown documents:
proposal.md: Why are we doing this? What capabilities are affected?design.md: How are we going to build it technically? (Decisions, Trade-offs)specs/<capability>/spec.md: What exactly must it do? (Formal requirements and testable scenarios)tasks.md: A trackable checklist of implementation steps.
-
Implementation: Once all artifacts are approved, the actual coding begins, using
tasks.mdas the source of truth./opsx:apply
-
Archive: When the code is merged and tasks are complete, the change is archived. If any specs were modified, they are automatically synced to the main
openspec/specs/directory, acting as living documentation for the project./opsx:archive
If you are proposing a significant architecture shift or new feature, please draft a change proposal via OpenSpec!