Release Process
Branching Model
develop is the integration branch: PRs from feature/fix branches land there
first. main only ever receives merges from develop (or a release/* /
hotfix/* branch cut from it) via pull request — no direct pushes. This is
enforced by branch protection on main (pull request required; the
github-actions bot is exempted so the automated manifest-update commits
described below can still land).
feature/fix branches ──PR──> develop ──PR──> main ──tag──> GitHub Release
│
└─ every push (that touches server, bot
or plugin/client code) publishes a
rolling "dev" build of what changed
Versioning
JellyWatchParty uses Semantic Versioning:
MAJOR.MINOR.PATCH
- MAJOR: Breaking changes
- MINOR: New features (backwards compatible)
- PATCH: Bug fixes (backwards compatible)
Builds published from develop (Docker dev tag, plugin develop channel)
use their own non-conflicting scheme — see
Develop Builds below — and are never meant to be
tagged as a release themselves.
Release Checklist
Pre-Release
- All tests pass
- Documentation updated
- CHANGELOG updated
- Version numbers updated
- Manual testing completed
Version Locations
Update version in:
- Rust (
src/server/Cargo.toml,src/integrations/discord-bot/Cargo.toml):[package] version = "0.2.0" - C# Plugin (
.csproj):<Version>0.2.0</Version> - Plugin metadata (
Plugin.cs) if applicable
CHANGELOG Format
# Changelog
## [0.2.0] - 2024-01-15
### Added
- New feature description
### Changed
- Change description
### Fixed
- Bug fix description
### Security
- Security fix description
## [0.1.0] - 2024-01-01
Initial release.
Build Process
Build All Components
just build
Build Individually
# Rust session server
cd src/server
cargo build --release
# C# plugin - builds net10.0 (Jellyfin 12.x)
cd src/plugins/jellyfin/JellyWatchParty
dotnet build -c Release
Build Artifacts
| Component | Output Location |
|---|---|
| Session Server | src/server/target/release/session-server |
| Session Server (Windows) | jwp-session-server-windows-vX.Y.Z.zip (CI-built, attached to GitHub Release) |
| Discord Bot | src/integrations/discord-bot/target/release/jwp-discord-bot |
| Plugin DLL (Jellyfin 12.x) | src/plugins/jellyfin/JellyWatchParty/bin/Release/net10.0/JellyWatchParty.dll |
Release Steps
Release branches fork from develop, land on main via pull request, get
tagged there, and merge back into develop so both branches stay in sync.
1. Create Release Branch
git checkout develop
git pull origin develop
git checkout -b release/v0.2.0
2. Update Versions
Update all version numbers as listed above.
3. Update CHANGELOG
4. Commit Changes
git add -A
git commit -m "Release v0.2.0"
git push origin release/v0.2.0
5. Open a Pull Request into main
Open the PR from release/v0.2.0 into main, get it reviewed, and merge it
(branch protection requires this — there is no direct push to main).
6. Create Tag (on main, after the merge)
git checkout main
git pull origin main
git tag -a v0.2.0 -m "Version 0.2.0"
git push origin v0.2.0
7. Create GitHub Release
Using the GitHub CLI (recommended):
gh release create v0.2.0 --title "v0.2.0"
Or via GitHub UI:
- Go to GitHub > Releases > New Release
- Select tag
v0.2.0 - Title:
v0.2.0 - Description: Copy from CHANGELOG
- Click Publish release
The workflow will automatically:
- Build and push the session server and Discord bot Docker images to GHCR
(
latest,X.Y.Z,X.Y) - Build and attach a Jellyfin plugin zip (targeting Jellyfin 12.x)
- Build and attach a standalone Windows session server binary
- Update
manifest.jsonwith the newtargetAbi 12.0.0.0entry
8. Merge Back into develop
Keep develop up to date with the release commit (version bumps, changelog)
via a PR from main into develop:
git checkout develop
git pull origin develop
git merge main
git push origin develop
9. Clean Up
git branch -d release/v0.2.0
Docker Images
Docker images are automatically built (linux/amd64 and linux/arm64) and
pushed to GitHub Container Registry (GHCR) by .github/workflows/publish.yml,
which runs .github/workflows/docker-image.yml once per image:
| Image | Built from | Rebuilt on push when these change |
|---|---|---|
ghcr.io/tigamingtv/jwp-session-server |
src/server, infra/docker/server.Dockerfile |
src/server/**, the Dockerfile, docker-image.yml |
ghcr.io/tigamingtv/jwp-discord-bot |
src/integrations/discord-bot, infra/docker/discord-bot.Dockerfile |
src/integrations/discord-bot/**, the Dockerfile, docker-image.yml |
A release always rebuilds both.
Available Tags
Both images get the same tags, so the bot can be pinned to the server’s version.
| Tag | Description | Updated |
|---|---|---|
latest |
Latest stable release | On release |
X.Y.Z |
Specific version (release v0.1.0 -> 0.1.0) |
On release |
X.Y |
Minor version (e.g., 0.1) |
On release |
beta |
Latest build from main |
On push to main (image’s code changed) |
dev |
Latest build from develop |
On push to develop (image’s code changed) |
The v of the release tag is dropped from image tags.
Pull Images
# Latest stable
docker pull ghcr.io/tigamingtv/jwp-session-server:latest
docker pull ghcr.io/tigamingtv/jwp-discord-bot:latest
# Specific version
docker pull ghcr.io/tigamingtv/jwp-session-server:0.1.0
docker pull ghcr.io/tigamingtv/jwp-discord-bot:0.1.0
# Latest from main
docker pull ghcr.io/tigamingtv/jwp-session-server:beta
docker pull ghcr.io/tigamingtv/jwp-discord-bot:beta
# Latest from develop
docker pull ghcr.io/tigamingtv/jwp-session-server:dev
docker pull ghcr.io/tigamingtv/jwp-discord-bot:dev
infra/docker/prod/docker-compose.yml uses these images; JWP_TAG picks the
tag for both (default latest):
JWP_TAG=dev docker compose -f infra/docker/prod/docker-compose.yml --profile discord pull
JWP_TAG=dev docker compose -f infra/docker/prod/docker-compose.yml --profile discord up -d
Package Visibility
GHCR creates a package as private the first time it is pushed. After the
first publish of a new image (for jwp-discord-bot, the first push to
develop with this workflow), open the repository’s Packages >
the package > Package settings > Change visibility and make it
Public, or nobody can pull it without logging in.
Build Locally (optional)
docker build -f infra/docker/server.Dockerfile --build-arg BUILD_MODE=release \
-t jwp-session-server:local ./src/server
docker build -f infra/docker/discord-bot.Dockerfile \
-t jwp-discord-bot:local ./src/integrations/discord-bot
Develop Builds
Every push to develop that touches the relevant code publishes a rolling
build, so testers always have the latest in-progress version of every
component without waiting for a tagged release.
| Component | Where it lands | Version scheme |
|---|---|---|
| Session Server | Docker image ghcr.io/tigamingtv/jwp-session-server:dev |
Tag stays dev, content changes each push |
| Discord Bot | Docker image ghcr.io/tigamingtv/jwp-discord-bot:dev |
Tag stays dev, content changes each push |
| Jellyfin Plugin | Rolling pre-release develop-latest, tracked via manifest-dev.json |
0.0.<GitHub run number> (always increasing, always below 1.0) |
Develop Plugin Channel
The plugin’s develop builds are exposed as a second, separate Jellyfin
plugin repository so they can be installed/updated like a beta channel,
without touching the stable manifest.json feed:
- Go to Dashboard > Plugins > Repositories
- Add:
https://tigamingtv.github.io/JellyWatchParty/jellyfin-plugin-repo/manifest-dev.json - Go to Catalog > Find “JellyWatchParty (Develop)” > Install
- Restart Jellyfin
Because dev versions are always 0.0.x (below any real 1.x release), it’s
safe to have both the stable and dev repositories added at once — Jellyfin
will prefer whichever is numerically higher, so a stable release always wins
over the dev channel once one exists past 0.0.x. Uninstall the dev-channel
entry if you no longer want to test pre-release builds.
Automated Releases
Releases are fully automated via GitHub Actions (.github/workflows/publish.yml).
What Happens on Release
When you create a GitHub Release:
- Docker Image: Built for amd64 and arm64, pushed to GHCR with version +
latesttags - Jellyfin Plugin: Built for Jellyfin 12.x, zipped, and attached to the release
- Windows Session Server: Built natively on
windows-latest, zipped with asession-server.exeand a short usage README, and attached to the release — no Docker or Rust install required to run it - Plugin Repository:
manifest.jsonupdated with new version and deployed to GitHub Pages
What Happens on Push to main
When server code changes (src/server/**) are pushed to main:
- Docker Image: Built and pushed with
betatag - Allows testers to always have the latest development version
What Happens on Push to develop
- Server changed: Docker image built and pushed with the
devtag - Plugin/client changed: plugin rebuilt for Jellyfin 12.x, attached to
the rolling
develop-latestpre-release, andmanifest-dev.jsonupdated — see Develop Builds
A changes job in publish.yml (via dorny/paths-filter) detects which of
the two actually changed, so an unrelated change doesn’t trigger a rebuild
of the other component.
Plugin Distribution
Users can install the plugin in three ways:
Via Jellyfin UI (Recommended, stable)
- Go to Dashboard > Plugins > Repositories
- Add:
https://tigamingtv.github.io/JellyWatchParty/jellyfin-plugin-repo/manifest.json - Go to Catalog > Find “JellyWatchParty” > Install
- Restart Jellyfin
Via Jellyfin UI (develop/beta channel)
See Develop Plugin Channel above.
Via Direct Download
- Go to Releases
- Download
JellyWatchParty-vX.Y.Z.zip(targets Jellyfin 12.x; for 10.11.x, download an older release instead) - Extract to Jellyfin plugins folder
- Restart Jellyfin
Hotfix Process
For critical bug fixes:
- Branch from the release tag:
git checkout -b hotfix/v0.2.1 v0.2.0 -
Apply fix and commit
-
Update patch version
- Follow normal release process with new tag
v0.2.1(PR intomain, tag, release, then merge back intodevelop)
Deprecation Policy
- Announce deprecations in release notes
- Maintain for at least one minor version
- Provide migration guide when removing features
Rollback Process
If a release has critical issues:
- Immediate: Advise users to use previous version
- GitHub: Mark release as pre-release or delete
- Fix: Create hotfix release
- Communicate: Update issue/discussion with status
Release Communication
Channels
- GitHub Releases (primary)
- GitHub Discussions (announcements)
- Jellyfin forums (if applicable)
Template
## What's New
Brief summary of changes.
## Highlights
- Feature 1
- Feature 2
## Breaking Changes
List any breaking changes and migration steps.
## Installation
See [Installation Guide](docs/installation.md).
## Upgrading
See [Upgrade Procedure](docs/deployment.md#upgrade-procedure).
## Changelog
Next Steps
- Contributing - How to contribute
- Testing - Testing before release
- Deployment - Production deployment