Template CI/CD untuk game jam berguna ketika tim harus merilis build baru dalam hitungan menit, bukan jam. Dalam konteks game jam atau sprint produk cepat, target utamanya bukan pipeline yang sempurna, melainkan pipeline yang cukup ketat untuk mencegah error dasar, cukup cepat untuk dipakai terus-menerus, dan cukup sederhana agar bisa dirawat oleh tim kecil.

Jika Anda mengerjakan game web berbasis JavaScript, workflow minimal yang biasanya paling efektif adalah: jalankan lint, jalankan test minimum yang cepat, lakukan build otomatis, simpan artifact untuk preview, lalu rilis otomatis saat tag dibuat. Artikel ini fokus pada implementasi teknis dengan GitHub Actions, termasuk trade-off antara pipeline cepat dan coverage tinggi, strategi fail-fast, serta kapan aman melewati test tertentu.

Mengapa game jam butuh CI/CD yang ringan

Tren game jam yang ramai dibahas komunitas developer sering mendorong tim untuk mengirim build lebih sering: memperbaiki bug kecil, mengganti aset, menyesuaikan balancing, atau merapikan loading awal. Masalahnya, semakin sering Anda membangun dan mengunggah build secara manual, semakin besar peluang muncul error yang sebenarnya bisa dicegah sejak awal.

CI/CD ringan membantu pada titik yang paling penting:

  • Mencegah commit rusak masuk ke branch utama lewat lint dan test singkat.
  • Menghasilkan build yang konsisten tanpa bergantung pada mesin lokal salah satu anggota tim.
  • Menyediakan artifact preview agar tim QA internal atau desainer bisa mengecek hasil tanpa harus menjalankan proyek dari source.
  • Mempercepat release dengan tag version yang langsung memicu paket rilis.

Untuk game jam, tujuan praktisnya bukan mengejar coverage maksimal. Tujuannya adalah menutup risiko yang paling sering terjadi: typo, import rusak, build gagal, asset path salah, dan perubahan yang tidak lagi bisa dipaketkan menjelang deadline.

Struktur repository yang sederhana dan tahan pakai

Struktur repo tidak harus rumit, tetapi sebaiknya memisahkan kode aplikasi, aset, script otomatisasi, dan workflow CI. Contoh struktur yang umum untuk game JavaScript berbasis web:

repo-root/
├─ src/
│  ├─ game/
│  ├─ ui/
│  ├─ assets/
│  └─ main.js
├─ public/
├─ tests/
│  ├─ smoke/
│  └─ unit/
├─ scripts/
│  ├─ verify-assets.js
│  └─ version-name.js
├─ .github/
│  └─ workflows/
│     └─ ci.yml
├─ package.json
├─ package-lock.json
├─ .eslintrc.json
└─ README.md

Beberapa catatan praktis:

  • tests/smoke dipakai untuk test minimum yang sangat cepat, misalnya memastikan modul inti dapat diimpor, konfigurasi level valid, atau state awal game tidak melempar exception.
  • scripts/verify-assets.js berguna untuk memeriksa file asset yang sering menyebabkan build lolos tetapi game rusak saat runtime, misalnya path gambar yang salah.
  • public/ atau folder output statis sebaiknya konsisten agar artifact dan deploy lebih mudah.

Untuk tim kecil, struktur ini cukup tanpa menambah lapisan kompleksitas seperti mono-repo atau beberapa pipeline terpisah. Mono-repo masuk akal jika Anda memang punya editor tools, backend, dan game client dalam satu proyek, tetapi untuk game jam biasanya itu justru menambah overhead.

Linting, test minimum, dan aturan fail-fast

Linting: wajib, cepat, dan murah

Lint adalah pemeriksaan paling murah dengan dampak paling besar. Ia menangkap kesalahan sintaks, variabel tidak terpakai, import yang keliru, atau pola kode yang berisiko sebelum masuk ke tahap build. Untuk proyek game JavaScript, lint sebaiknya selalu dijalankan pada pull request dan sebelum merge ke branch utama.

Contoh script pada package.json:

{
  "scripts": {
    "lint": "eslint src tests scripts",
    "test": "npm run test:smoke && npm run test:unit",
    "test:smoke": "node --test tests/smoke/**/*.test.js",
    "test:unit": "node --test tests/unit/**/*.test.js",
    "build": "vite build",
    "verify:assets": "node scripts/verify-assets.js"
  }
}

Nama tool build di atas hanya contoh yang umum untuk proyek web JavaScript. Jika Anda memakai bundler lain, prinsip CI/CD-nya tetap sama: lint dulu, test cepat dulu, baru build.

Test minimum yang realistis untuk game jam

Game jam jarang punya waktu untuk test end-to-end lengkap. Karena itu, fokuskan test pada area yang paling sering pecah:

  • Smoke test untuk memastikan aplikasi bisa start tanpa crash.
  • Unit test terbatas untuk logika skor, collision sederhana, parsing data level, atau helper penting.
  • Verifikasi asset/config untuk file JSON, daftar level, atau path asset yang wajib ada.

Kesalahan umum adalah langsung menambahkan banyak test yang lambat, lalu pipeline menjadi diabaikan karena hasilnya terlalu lama keluar. Dalam game jam, test minimum yang selalu dijalankan lebih berguna daripada suite besar yang sering dimatikan.

Strategi fail-fast

Fail-fast berarti menghentikan pipeline secepat mungkin ketika syarat dasar gagal. Urutan yang disarankan:

  1. Install dependency.
  2. Lint.
  3. Smoke test dan validasi asset.
  4. Unit test singkat.
  5. Build.

Urutan ini efektif karena:

  • Lint sering gagal lebih cepat daripada build.
  • Smoke test biasanya jauh lebih murah daripada menjalankan test penuh.
  • Build diletakkan belakangan agar resource tidak terbuang saat kesalahan dasar sudah terlihat.

Untuk game jam, build yang cepat tetapi sering gagal karena error dasar lebih buruk daripada pipeline yang sedikit lebih ketat namun memberi sinyal kegagalan lebih awal.

Contoh GitHub Actions untuk project game web JavaScript

Berikut contoh workflow GitHub Actions yang cukup ringan untuk tim kecil. Workflow ini memicu job pada pull request, push ke branch utama, dan tag release. Ia mencakup cache dependency, lint, test, build, upload artifact, dan pembuatan release saat tag dibuat.

name: ci-cd-gamejam

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
    tags:
      - 'v*'

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Verify assets
        run: npm run verify:assets

      - name: Run smoke tests
        run: npm run test:smoke

      - name: Run unit tests
        run: npm run test:unit

  build:
    runs-on: ubuntu-latest
    needs: quality
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build game
        run: npm run build

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: game-web-build
          path: dist/

  release:
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    needs: build
    permissions:
      contents: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build release
        run: npm run build

      - name: Archive build
        run: |
          cd dist
          zip -r ../game-web-release.zip .

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: game-web-release.zip

Ada beberapa hal penting dari workflow di atas:

  • pull_request memastikan validasi terjadi sebelum merge.
  • needs: quality membuat build hanya berjalan jika lint dan test lolos.
  • Cache npm mengurangi waktu instalasi dependency, terutama jika lockfile stabil.
  • Artifact build memungkinkan anggota tim mengunduh hasil build tanpa menunggu release formal.
  • Trigger tag v* memberi jalur rilis yang jelas dan mudah dipahami.

Mengapa build diulang pada job release

Sekilas terlihat duplikatif karena build dijalankan lagi pada job release. Namun ini sering dipilih demi kesederhanaan: setiap job berjalan di environment baru, dan memindahkan artifact antar job kadang lebih rumit daripada membangun ulang, terutama jika proyek masih kecil. Jika build Anda berat, Anda bisa mengunduh artifact dari job sebelumnya lalu mengemasnya untuk release.

Kapan matrix build diperlukan

Untuk game web, satu target Linux runner biasanya cukup. Jangan menambah matrix lintas sistem operasi jika tidak ada kebutuhan nyata, karena itu memperlambat feedback. Matrix build lebih relevan jika Anda menghasilkan binary desktop atau punya dependency platform-specific.

Artifact preview dan alur review internal

Artifact preview membantu tim non-programmer. Setelah pull request dibuat, hasil build dapat diunduh sebagai artifact dan diuji oleh desainer, artist, atau game designer tanpa harus menyiapkan environment pengembangan.

Beberapa praktik yang berguna:

  • Gunakan nama artifact yang konsisten, misalnya game-web-build.
  • Pastikan output build berada di folder tetap, misalnya dist/.
  • Sertakan commit SHA atau nomor run jika Anda punya lebih dari satu build per hari.

Jika tim butuh preview yang lebih mudah diakses, Anda bisa menambahkan deploy ke static hosting pada branch tertentu. Namun untuk game jam, artifact download sering sudah cukup dan lebih aman karena tidak menambah konfigurasi domain, secret, atau target hosting.

Penamaan versi yang praktis untuk rilis cepat

Pada game jam, versi tidak harus rumit. Yang penting: mudah dilacak, konsisten, dan terlihat jelas di release notes maupun file build. Pendekatan paling aman adalah memakai tag yang dapat dibaca manusia, misalnya:

  • v0.1.0 untuk milestone awal yang bisa dimainkan.
  • v0.1.1 untuk perbaikan bug ringan.
  • v0.2.0 saat ada perubahan signifikan pada mekanik atau konten.

Jika ritme rilis sangat cepat, Anda bisa menambahkan metadata di nama file artifact, misalnya tanggal atau short commit SHA. Namun untuk tag Git, tetap jaga format sederhana agar trigger release mudah dipahami.

Contoh sederhana menghasilkan nama versi dari tag atau commit:

// scripts/version-name.js
const version = process.env.GITHUB_REF_NAME || process.env.GITHUB_SHA || 'dev';
console.log(version);

Script seperti ini berguna jika Anda ingin menampilkan versi di layar menu game atau menyisipkannya ke metadata build. Manfaatnya besar saat tim menerima laporan bug seperti, “build yang mana yang sedang diuji?”

Trade-off: pipeline cepat vs coverage tinggi

Ini bagian yang paling sering disalahpahami. Dalam sprint cepat, pipeline yang terlalu lengkap bisa menjadi hambatan. Di sisi lain, pipeline yang terlalu longgar membuat bug lolos terlalu jauh. Pilihannya bukan hitam-putih; Anda perlu memisahkan validasi wajib dan validasi ideal.

Yang sebaiknya selalu wajib

  • Install dependency bersih dengan npm ci.
  • Lint.
  • Smoke test.
  • Validasi asset atau config penting.
  • Build produksi.

Yang bisa dijalankan selektif

  • Test unit yang lebih banyak tetapi lambat.
  • End-to-end test di browser.
  • Visual regression test.
  • Scan tambahan yang berat.

Strategi yang umum dan aman:

  • Jalankan validasi cepat di setiap pull request.
  • Jalankan test yang lebih berat hanya pada push ke main, nightly run, atau sebelum submission final.
  • Lewati test mahal jika perubahan hanya menyentuh dokumentasi, metadata, atau asset non-kritis.

Kapan aman melewati test tertentu

Melewati test bisa diterima jika dilakukan secara sadar dan terdokumentasi. Misalnya:

  • Perubahan README atau deskripsi jam submission: aman tanpa test penuh.
  • Perubahan asset statis yang tidak memengaruhi pipeline runtime: tetap jalankan verifikasi asset, tetapi unit test logika bisa diprioritaskan lebih rendah.
  • Perbaikan teks UI: smoke test dan build biasanya cukup.

Yang tidak aman untuk dilewati:

  • Perubahan dependency.
  • Perubahan bundler atau konfigurasi build.
  • Perubahan loading asset, scene initialization, routing layar, atau save data.

Kesalahan umum adalah menggunakan argumen “demi cepat” untuk mematikan test justru pada area yang paling rawan pecah. Jika Anda ingin melewati test, batasi hanya untuk perubahan yang risikonya benar-benar kecil.

Checklist release untuk game jam

Checklist release membantu mencegah hal sepele yang sering lolos ketika deadline makin dekat. Simpan checklist ini di README atau issue template.

  1. Semua PR penting sudah merge ke branch utama.
  2. Lint, smoke test, dan build produksi lolos.
  3. Asset utama tersedia dan path-nya valid.
  4. Versi/tag release dibuat dengan format konsisten.
  5. Artifact build dapat dijalankan oleh anggota tim lain.
  6. Menu awal, input dasar, audio, dan transisi scene dicek manual.
  7. Ukuran bundle atau asset tidak melonjak tanpa alasan jelas.
  8. Catatan rilis singkat ditulis agar tim tahu isi perubahan.

Untuk game, sanity check manual tetap penting meskipun CI sudah hijau. Pipeline bisa memastikan build berhasil, tetapi belum tentu memastikan gameplay terasa benar, audio sinkron, atau UI tidak tertutup di resolusi tertentu.

Debugging saat workflow CI/CD gagal

Build lokal sukses, CI gagal

Biasanya penyebabnya salah satu dari berikut:

  • Dependency lokal berbeda dengan lockfile.
  • Path file berbeda huruf besar-kecil, yang sering lolos di mesin tertentu tetapi gagal di Linux runner.
  • Environment variable tidak tersedia di CI.
  • File asset ada di mesin lokal tetapi belum ter-commit.

Langkah pertama yang paling efektif adalah menjalankan npm ci dan npm run build di environment bersih secara lokal, bukan memakai node_modules lama.

Lint sering gagal karena rule yang tidak relevan

Jangan langsung mematikan ESLint seluruhnya. Lebih baik sederhanakan rule agar hanya menangkap masalah yang memang penting untuk proyek. Lint yang terlalu cerewet akan diabaikan; lint yang fokus justru dipakai terus.

Test flaky

Test flaky sangat berbahaya untuk game jam karena mengikis kepercayaan tim pada pipeline. Jika ada test yang kadang gagal tanpa perubahan kode:

  • Periksa ketergantungan pada waktu, random seed, atau urutan eksekusi.
  • Jangan jadikan test flaky sebagai syarat merge sebelum diperbaiki.
  • Pisahkan test tersebut dari jalur wajib jika memang belum stabil.

Template minimum yang layak dipakai mulai hari ini

Jika Anda butuh keputusan cepat, gunakan baseline berikut:

  • Repo: pisahkan src, tests, scripts, dan .github/workflows.
  • PR check: npm ci, lint, verifikasi asset, smoke test.
  • Main branch: semua PR check + build artifact.
  • Tag release: build ulang, zip hasil build, publish GitHub Release.
  • Versioning: tag v0.x.y yang konsisten.
  • Manual check: jalankan game, cek input, scene awal, audio, dan loading.

Dengan template CI/CD untuk game jam seperti ini, Anda tidak mendapatkan coverage maksimal, tetapi Anda mendapat sesuatu yang lebih penting untuk sprint pendek: feedback cepat, build konsisten, dan jalur rilis yang tidak membuat panik menjelang deadline.