Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
af3d7fa
Add telepresence
Brutus5000 Nov 9, 2024
bfddcc9
Update telepresence-oss Docker tag to v2.25.1
renovate[bot] Nov 26, 2025
ac0bb25
Add replays old to content (#204)
Sheikah45 Mar 23, 2025
43239b1
not read only attempy
Sheikah45 Mar 23, 2025
31af66f
remove replays-old mount to nginx
Sheikah45 Mar 23, 2025
f016c9c
Change delay to 30 seconds
Sheikah45 May 3, 2025
0ab1567
Allow top players to match with anyone in the 1v1 queue (#211)
BlackYps May 8, 2025
597e7c4
Enable force relay
Brutus5000 Sep 5, 2025
775d397
ice-breaker set to trace (attempt 1)
Ivan-Shaml Sep 7, 2025
021e581
Drop promtail
p4block Sep 21, 2025
7dee4c6
Add a values for alloy prod
p4block Sep 21, 2025
1e68c27
Fix duped yaml key
p4block Sep 21, 2025
706b182
No affinity for loki gw
p4block Sep 21, 2025
5d0b23b
No affinity for loki
p4block Sep 21, 2025
daec309
Fix yaml
p4block Sep 21, 2025
8337ac1
Python server log level DEBUG
Brutus5000 Oct 21, 2025
09f7d2c
Drop promtail
p4block Sep 21, 2025
48ad7d3
Update faf-icebreaker to 1.2.0-RC2
Brutus5000 Dec 20, 2025
bf67b41
Enable Cloudflare
Brutus5000 Nov 23, 2025
12c4da1
Update icebreaker to RC4
Sheikah45 Dec 27, 2025
f23b8d8
Fix deploy coop maps
Brutus5000 Dec 27, 2025
3aef616
Fix deploy coop maps
Brutus5000 Dec 27, 2025
72f3370
Set up tilt CI for testing gitops-stack
Sheikah45 Dec 27, 2025
f63d42e
Add localhost endpoints and add jobs to support local games and services
Sheikah45 Dec 27, 2025
004ab03
Remove docker-based run_sql
Brutus5000 Dec 28, 2025
8f9d86f
Seems to work
Brutus5000 Dec 29, 2025
df19399
Try removing subpath again
Brutus5000 Dec 29, 2025
1d96397
Util class
Brutus5000 Dec 29, 2025
140e5ef
Update azure/setup-helm action to v4.3.1 (#270)
renovate[bot] Jan 1, 2026
0a88d4f
Update postgres Docker tag to v17.7
renovate[bot] Jan 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Checks

on:
push:
pull_request:
branches:
- develop

jobs:
checks:

runs-on: ubuntu-latest
container:
image: docker/tilt:latest

steps:
- uses: actions/checkout@v4

- uses: azure/[email protected]

- name: Create k8s Kind Cluster
run: ctlptl create cluster kind --registry=ctlptl-registry

- name: Test Using Local Config
run: tilt ci --timeout "5m"


12 changes: 9 additions & 3 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,21 @@ This repository aims to provide a ready-to-go [Tilt](https://docs.tilt.dev/) set
## Prerequisites
* [Tilt](https://docs.tilt.dev/install.html)
* Kubernetes ([Docker Desktop](https://docs.docker.com/desktop/kubernetes/) or [Minikube](https://minikube.sigs.k8s.io/docs/) are recommended for those new to kubernetes) [Tilt cluster setup](https://docs.tilt.dev/choosing_clusters)
* For Windows users a bash program. By default git bash is used with an assumed installation directory of C:/Program Files/Git
* [helm](https://helm.sh/docs/intro/install/) must be installed to generate the k8s from the helm charts in the gitops repo
* For Windows users:
* A bash program. By default git bash is used with an assumed installation directory of C:/Program Files/Git

## Startup Services
In the root directory of the repository run `tilt up`. This will start all the faf services in the correct order. The status of each service can be viewed in the tilt UI by visiting <http://localhost:10350>. This is the control server for tilt where you can restart services or disable them for substitution by services you would like to run from source code as you actively develop them.

## Development
To develop against the FAF infrastructure you should disable the service in tilt that you are actively developing. Once disabled you can start up your developed version. Some tweaks may need to be made to the default configuration parameters in the source code. The proper values can be found in the configMaps in each of the services kubernetes deploy yaml files.
To develop against the FAF infrastructure you can insert the service in tilt that you are actively developing by adding it to the local-services list in your tilt_config.json file or as --local-services when you run tilt up. This will proxy the connections in the cluster to that service to your locally running instance. Some tweaks may need to be made to the default configuration parameters in the source code. The proper values can be found in the configMaps in each of the services kubernetes deploy yaml files. You may need to specify your host-ip in the config or arguments in order to get the proxied connections to work

## Test Data
The default test data that is loaded can be found in /sql/test-data.sql. This can be overridden by providing a new path with the tilt configuration key test-data-path when running tilt up or in the tilt_config.json file in the repository root directory.
The default test data that is loaded can be found in [faf-db](https://github.com/FAForever/db/blob/develop/test-data.sql).
You can load the data at anytime by manually triggering the popualte-db resource under the Database label. This needs to be done the first time for data to exist.

## Endpoints
Locally traefik uses the same ingress routes as we do in production just with a default base domain of faforever.localhost. So accessible domains will be api.faforever.localhost, hydra.faforever.localhost etc. By default these should resolve to 127.0.0.1. If they do not you can manually modify your hosts file to add the local dns records. For convenience the resource create-hosts-file-content
will output the necessary lines for the hosts file when run after every service has started.

243 changes: 165 additions & 78 deletions Tiltfile

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions apps/faf-icebreaker/templates/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ data:
HYDRA_URL: "https://hydra.{{.Values.baseDomain}}"
SELF_URL: "https://ice.{{.Values.baseDomain}}"
DB_USERNAME: "faf-icebreaker"
DB_NAME: "faf-icebreaker"
DB_URL: "jdbc:mariadb://mariadb:3306/faf-icebreaker?ssl=false"
RABBITMQ_HOST: "rabbitmq"
RABBITMQ_USER: "faf-icebreaker"
RABBITMQ_PORT: "5672"
CLOUDFLARE_ENABLED: "false"
CLOUDFLARE_ENABLED: "true"
XIRSYS_ENABLED: "true"
XIRSYS_TURN_ENABLED: "true"
GEOIPUPDATE_EDITION_IDS: "GeoLite2-City"
LOKI_BASE_URL: "http://monitoring-loki-gateway.faf-ops.svc"
FORCE_RELAY: "false"
QUARKUS_LOG_CATEGORY__COM_FAFOREVER__LEVEL: "DEBUG"
FORCE_RELAY: "true"
REAL_IP_HEADER: "Cf-Connecting-Ip"
QUARKUS_LOG_CATEGORY__COM_FAFOREVER__LEVEL: "TRACE"
2 changes: 1 addition & 1 deletion apps/faf-icebreaker/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ spec:
- name: geolite-db
mountPath: /usr/share/GeoIP
containers:
- image: faforever/faf-icebreaker:1.1.9
- image: faforever/faf-icebreaker:1.2.0-RC4
imagePullPolicy: Always
name: faf-icebreaker
envFrom:
Expand Down
1 change: 1 addition & 0 deletions apps/faf-icebreaker/templates/local-secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ stringData:
RABBITMQ_PASSWORD: "banana"
XIRSYS_IDENT: "banana"
XIRSYS_SECRET: "banana"
HETZNER_API_KEY: "banana"
JWT_PRIVATE_KEY_PATH: |-
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXsCsl9W0vnW2k
Expand Down
88 changes: 18 additions & 70 deletions apps/faf-legacy-deployment/scripts/CoopDeployer.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import org.apache.commons.compress.archivers.zip.Zip64Mode
@file:Suppress("PackageDirectoryMismatch")

package com.faforever.coopdeployer

import com.faforever.FafDatabase
import com.faforever.GitRepo
import com.faforever.Log
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
import org.eclipse.jgit.api.Git
import org.slf4j.LoggerFactory
import java.io.IOException
import java.net.URI
Expand All @@ -15,12 +20,7 @@ import java.nio.file.StandardCopyOption
import java.nio.file.attribute.FileTime
import java.nio.file.attribute.PosixFilePermission
import java.security.MessageDigest
import java.sql.Connection
import java.sql.DriverManager
import java.time.Duration
import java.util.zip.CRC32
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.io.path.inputStream

private val log = LoggerFactory.getLogger("CoopDeployer")
Expand All @@ -34,33 +34,6 @@ fun Path.setPerm664() {
Files.setPosixFilePermissions(this, perms)
}

data class FeatureModGitRepo(
val workDir: Path,
val repoUrl: String,
val gitRef: String,
) {
fun checkout(): Path {
if (Files.exists(workDir.resolve(".git"))) {
log.info("Repo exists β€” fetching and checking out $gitRef...")
Git.open(workDir.toFile()).use { git ->
git.fetch().call()
git.checkout().setName(gitRef).call()
}
} else {
log.info("Cloning repository $repoUrl")
Git.cloneRepository()
.setURI(repoUrl)
.setDirectory(workDir.toFile())
.call()
log.info("Checking out $gitRef")
Git.open(workDir.toFile()).use { git ->
git.checkout().setName(gitRef).call()
}
}

return workDir
}
}

data class GithubReleaseAssetDownloader(
val repoOwner: String = "FAForever",
Expand Down Expand Up @@ -160,25 +133,14 @@ data class GithubReleaseAssetDownloader(

}

data class FafDatabase(
val host: String,
val database: String,
val username: String,
val password: String,
data class CoopDatabase(
val dryRun: Boolean
) : AutoCloseable {
) : FafDatabase() {
/**
* Definition of an existing file in the database
*/
data class PatchFile(val mod: String, val fileId: Int, val name: String, val md5: String, val version: Int)

private val connection: Connection =
DriverManager.getConnection(
"jdbc:mariadb://$host/$database?useSSL=false&serverTimezone=UTC",
username,
password
)

fun getCurrentPatchFile(mod: String, fileId: Int): PatchFile? {
val sql = """
SELECT uf.fileId, uf.name, uf.md5, t.v
Expand All @@ -191,7 +153,7 @@ data class FafDatabase(
WHERE uf.fileId = ?
""".trimIndent()

connection.prepareStatement(sql).use { stmt ->
prepareStatement(sql).use { stmt ->
stmt.setInt(1, fileId)
val rs = stmt.executeQuery()
while (rs.next()) {
Expand All @@ -213,23 +175,19 @@ data class FafDatabase(
}
val del = "DELETE FROM updates_${mod}_files WHERE fileId=? AND version=?"
val ins = "INSERT INTO updates_${mod}_files (fileId, version, name, md5, obselete) VALUES (?, ?, ?, ?, 0)"
connection.prepareStatement(del).use {
prepareStatement(del).use {
it.setInt(1, fileId)
it.setInt(2, version)
it.executeUpdate()
}
connection.prepareStatement(ins).use {
prepareStatement(ins).use {
it.setInt(1, fileId)
it.setInt(2, version)
it.setString(3, name)
it.setString(4, md5)
it.executeUpdate()
}
}

override fun close() {
connection.close()
}
}

private const val MINIMUM_ZIP_DATE = 315532800000L // 1980-01-01
Expand All @@ -238,7 +196,7 @@ private val MINIMUM_ZIP_FILE_TIME = FileTime.fromMillis(MINIMUM_ZIP_DATE)
class Patcher(
val patchVersion: Int,
val targetDir: Path,
val db: FafDatabase,
val db: CoopDatabase,
val dryRun: Boolean,
) {
/**
Expand Down Expand Up @@ -409,22 +367,18 @@ class Patcher(
}

fun main() {
Log.init()

val PATCH_VERSION = System.getenv("PATCH_VERSION") ?: error("PATCH_VERSION required")
val REPO_URL = System.getenv("GIT_REPO_URL") ?: "https://github.com/FAForever/fa-coop.git"
val GIT_REF = System.getenv("GIT_REF") ?: "v$PATCH_VERSION"
val WORKDIR = System.getenv("GIT_WORKDIR") ?: "/tmp/fa-coop-kt"
val WORKDIR = System.getenv("GIT_WORKDIR") ?: "/tmp/fa-coop"
val DRYRUN = (System.getenv("DRY_RUN") ?: "false").lowercase() in listOf("1", "true", "yes")

val DB_HOST = System.getenv("DATABASE_HOST") ?: "localhost"
val DB_NAME = System.getenv("DATABASE_NAME") ?: "faf"
val DB_USER = System.getenv("DATABASE_USERNAME") ?: "root"
val DB_PASS = System.getenv("DATABASE_PASSWORD") ?: "banana"

val TARGET_DIR = Paths.get("./legacy-featured-mod-files")

log.info("=== Kotlin Coop Deployer v{} ===", PATCH_VERSION)

val repo = FeatureModGitRepo(
val repo = GitRepo(
workDir = Paths.get(WORKDIR),
repoUrl = REPO_URL,
gitRef = GIT_REF
Expand Down Expand Up @@ -476,13 +430,7 @@ fun main() {
Patcher.PatchFile(25, "FAF_Coop_Operation_Tight_Spot_VO.v%d.nx2", null),
)

FafDatabase(
host = DB_HOST,
database = DB_NAME,
username = DB_USER,
password = DB_PASS,
dryRun = DRYRUN
).use { db ->
CoopDatabase(dryRun = DRYRUN).use { db ->
val patcher = Patcher(
patchVersion = PATCH_VERSION.toInt(),
targetDir = TARGET_DIR,
Expand Down
Loading