Impulse AI Docs
Intern dokumentasjon
skipLink.label

CI/CD Pipeline

Alt du trenger for a forsta og bruke CI/CD-pipelinen i Impulse AI. Skrevet for soloutviklere som vil ha full kontroll uten a vaere DevOps-ekspert.

Hurtigreferanse

heading.anchorLabel
OppgaveKommando
Ny feature-branchgit checkout -b feat/min-feature
Kjor med secrets lokaltdoppler run -- pnpm dev
Promoter staging til production/deploy-prod eller git push origin main:production
iOS til TestFlightfastlane ios bump type:patch (oppretter git tag v*)
Promoter til App Store/promote eller fastlane ios promote
Manuell DB-migrasjondb-deploy.yml -> dry-run / migrate
Sjekk CI-statusgh run list --limit 5

1. Hva er CI/CD?

heading.anchorLabel

CI/CD star for Continuous Integration (CI) og Continuous Deployment (CD). I praksis betyr det at koden din blir automatisk testet og deployet nar du pusher den til GitHub.

Continuous Integration (CI)

heading.anchorLabel

Hver gang du pusher kode eller apner en pull request, kjorer GitHub Actions automatisk en serie sjekker: linting, typechecking, tester, kompilering. Alt dette skjer for koden merges til main.

Continuous Deployment (CD)

heading.anchorLabel

Nar kode er merget til main, deployes DB+API automatisk til staging (Railway + Supabase staging). Nar du promoterer til production (git push origin main:production), deployes DB+API til production (Railway + Supabase production).

iOS har en separat release-syklus: git tags (v*) trigger TestFlight-bygg via Fastlane, og promotering til App Store gjores manuelt.

Hvorfor er dette viktig for en soloutvikler?

heading.anchorLabel
  • Sikkerhetsnett: CI fanger feil for de nar brukerne. Du har ikke et QA-team — CI er QA-teamet ditt.
  • Konsistens: Deploy-prosessen er identisk hver gang, uansett om det er mandagsmorgen eller fredagskveld.
  • Hastighet: En git tag er alt som trengs for a release. Ingen manuell building, uploading, eller huskelister.
  • Trygghet: Du kan merge med selvtillit fordi du vet at alt er sjekket.

2. Arkitekturoversikt

heading.anchorLabel

Her er hele pipelinen visualisert — fra du skriver kode lokalt til den er live i produksjon:

Full pipeline

heading.anchorLabel
Lokal dev ──> Feature branch ──> CI Preflight ──> Merge til main
(din maskin) (git push) (GitHub Actions) (PR godkjent)
DB + API (tett koblet):
main branch ──> ┌─ DB staging ┐
(push trigger) └─ API staging ┘── STAGING (Railway staging + Supabase staging)
main:production ─> ┌─ DB prod ┐
(/deploy-prod) └─ API prod ┘── PRODUCTION (Railway prod + Supabase prod)
iOS (separat syklus):
git tag v* ──> TestFlight ──> App Store
(fastlane) (automatisk) (manuell promote)

Systemer involvert

heading.anchorLabel
SystemRolleTrigger
GitHub ActionsKjorer CI-sjekker og orkestrerer deploysPush, PR, git tag
DopplerSecrets management — erstatter .env-filerInjiseres automatisk
SupabaseDatabase (PostgreSQL) + AuthMigrasjoner ved deploy
RailwayAPI-server hosting (Fastify)Staging: auto-deploy fra main. Prod: auto-deploy fra production
VercelWeb-app hosting (Next.js)Auto-deploy fra main
FastlaneiOS build-automatiseringKalles fra GitHub Actions
App Store ConnectTestFlight-distribusjon og App StoreUpload fra Fastlane

3. Secrets Management med Doppler

heading.anchorLabel

Hva er Doppler? Doppler er en sentral plattform for a haandtere secrets (API-nokler, passord, konfigurasjon). Istedenfor a ha .env-filer liggende lokalt som du maa holde synkronisert, lever alle secrets i Doppler og injiseres automatisk der de trengs.

De tre konfigurasjonene

heading.anchorLabel

Doppler har tre separate configs som matcher dine miljoer:

ConfigMiljoBrukes av
devLokal utviklingDin maskin via doppler run
stgStagingGitHub Actions (CI + staging deploy)
prdProductionGitHub Actions (prod deploy)

Hvordan secrets flyter

heading.anchorLabel
┌─ doppler run ────────────> din terminal
Doppler ────────┼─ DOPPLER_TOKEN_STG ──────> GitHub Actions (CI)
(sentralt lager)│
└─ DOPPLER_TOKEN_PRD ──────> GitHub Actions (prod deploy)

Bruke Doppler lokalt

heading.anchorLabel

Prosjektet har en doppler.yaml i roten som setter opp riktig prosjekt og config:

setup:
- project: im
config: dev

Etter forste gangs oppsett (doppler login + doppler setup), kjorer du all lokal utvikling med:

Terminal window
# Starter dev-server med alle secrets injisert som env vars
doppler run -- pnpm dev
# Eller bare API-serveren
doppler run -- pnpm --filter api dev

Legge til eller oppdatere en secret

heading.anchorLabel
  1. Ga til Doppler Dashboard (app.doppler.com) — velg prosjektet “im” og riktig config (dev/stg/prd)
  2. Legg til eller endre secret — klikk “Add Secret” eller rediger en eksisterende. Gjor dette for alle configs der den trengs.
  3. Bruk den — lokalt: restart doppler run -- pnpm dev. I CI: automatisk tilgjengelig neste kjoring.

Key rotation (bytte en noekkel)

heading.anchorLabel
  1. Generer ny noekkel hos tjenesteleverandoren (f.eks. Anthropic, Supabase)
  2. Oppdater i Doppler for alle miljoer (dev, stg, prd)
  3. Restart/redeploy — lokalt: restart doppler run. Staging/prod: trigger ny deploy.
  4. Revoke gammel noekkel hos tjenesteleverandoren

4. GitHub Actions — Hva skjer nar du pusher kode?

heading.anchorLabel

Nar du pusher til en branch eller apner en PR mot main, starter ci.yml automatisk. Her er en oversikt over hva som skjer:

Steg 1: Detect Changes

heading.anchorLabel

Forste jobb bruker dorny/paths-filter for a finne ut hvilke deler av monorepo-et som er endret. Dette betyr at hvis du bare har endret iOS-kode, kjorer ikke API-sjekkene. Effektivt og raskt.

FilterStier som overvakes
dbpackages/database/**
apiapps/api/**, packages/shared/**, packages/auth/**
packagespackages/**
iosapps/mobile-kmp/shared/**, apps/mobile-kmp/iosApp/**, Gradle-filer
androidapps/mobile-kmp/shared/**, apps/mobile-kmp/androidApp/**, Gradle-filer

Steg 2: Parallelle sjekker

heading.anchorLabel

Basert pa hvilke endringer som ble oppdaget, kjores relevante jobber parallelt:

Database Starter lokal Supabase, kjorer alle migrasjoner med supabase db reset, verifiserer at genererte TypeScript-typer er oppdaterte. Kjorer kun nar: packages/database/** er endret.

API Lint -> Type check (shared + auth + api) -> Test -> Build. Secrets hentes fra Doppler (stg). Kjorer nar: apps/api/** eller packages/** er endret.

iOS Preflight Kjorer pa macos-15. KMP shared-modul kompileres, deretter iOS simulator build via Fastlane preflight lane. Kjorer nar: KMP shared, iosApp, eller Gradle-filer er endret.

Android Preflight Kjorer pa ubuntu-latest. Bygger Android debug APK med assembleDebug. Kjorer nar: KMP shared, androidApp, eller Gradle-filer er endret.

Steg 3: CI Gate

heading.anchorLabel

Den siste jobben, CI Gate, venter pa alle andre jobber. Den feiler hvis noen av sjekkene feilet. Jobber som ble skippet (fordi de delene av koden ikke var endret) teller som ok.

Concurrency control

heading.anchorLabel

Workflowen bruker concurrency: ci-${{ github.ref }} med cancel-in-progress: true. Det betyr at hvis du pusher to ganger raskt etter hverandre pa samme branch, kanselleres den forste kjoringen automatisk. Ingen bortkastet tid.


5. Automatisk Deploy til Staging

heading.anchorLabel

Nar kode merges til main (push, ikke PR), skjer staging-deploy automatisk.

BranchMiljoURL
mainStagingapi-stg.impulseai.app
productionProductionapi.impulseai.app

Hva trigger staging?

heading.anchorLabel
if: github.ref == 'refs/heads/main' && github.event_name == 'push'

Database -> Staging Kjorer supabase db push mot staging-prosjektet. Secrets (project ref, access token) hentes fra Doppler via DOPPLER_TOKEN_STG. Kun nar DB-filer er endret.

API -> Staging Railway overvaker main-branchen og deployer automatisk. Ingen manuell handling nodvendig.


6. Release til Production

heading.anchorLabel

DB + API (tett koblet)

heading.anchorLabel

DB og API deployes sammen ved a promotere main til production-branchen:

Terminal window
# Promoter staging til production
git push origin main:production
# Eller via Claude Code:
/deploy-prod

Railway production-service overvaker production-branchen og deployer automatisk. Database-migrasjoner kjores mot produksjons-Supabase.

Forutsetning: Staging er testet og fungerer. main inneholder alltid den nyeste koden som er verifisert i staging.

iOS (separat release-syklus)

heading.anchorLabel

iOS har sin egen release-syklus, uavhengig av DB+API:

Terminal window
# 1. Bump versjon og opprett git tag
cd apps/mobile-kmp/iosApp
bundle exec fastlane ios bump type:patch # 1.0.0 -> 1.0.1
# Eller via Claude Code:
/release ios patch
# 2. Git tag v* trigger TestFlight-bygg automatisk

TestFlight -> App Store:

Etter at iOS-bygget er oppe pa TestFlight, tester du det manuelt. Nar du er fornoyd, promoterer du til App Store:

Terminal window
# Via Claude Code:
/promote
# Eller lokalt:
cd apps/mobile-kmp/iosApp
bundle exec fastlane ios promote
# Eller via GitHub Actions:
# Actions > "iOS Release (manual)" > Run workflow > Velg "promote"

7. Fastlane — iOS Build Pipeline

heading.anchorLabel

Hva er Fastlane? Fastlane er et Ruby-basert verktoy som automatiserer iOS (og Android) build, testing, og distribusjon. Istedenfor a gjore ting manuelt i Xcode, definerer du “lanes” (oppgaver) i en Fastfile.

Nokkelprinsipp: Fastfilen er “single source of truth”. GitHub Actions kaller bare Fastlane — all byggelogikk bor i Fastfilen.

Tilgjengelige lanes

heading.anchorLabel
LaneHva den gjorNar
preflightKMP compile + iOS simulator build (ingen signing)CI pa hver PR
testKjorer iOS-tester pa iPhone 16 simulatorLokal utvikling
betaSigning -> KMP release -> archive -> TestFlight uploadProduction deploy (git tag)
promoteSiste TestFlight-bygg -> App Store ConnectManuelt etter testing
releaseFull pipeline: beta + App Store uploadForce-release (manuelt)
bumpBump versjon (patch/minor/major) + commit + tagFor release
doctorHealth check: Gradle, Xcode, signing, ASC API keyDebugging

Signing med Match

heading.anchorLabel

Fastlane bruker Match for kodesignering. Match lagrer sertifikater og provisioning profiles i et privat Git-repo, slik at de kan deles mellom lokal maskin og CI.

Slik fungerer signing-flyten

heading.anchorLabel
  1. API-noekkel: App Store Connect API key (ASC_KEY_ID, ASC_ISSUER_ID, ASC_PRIVATE_KEY) injiseres fra Doppler.
  2. Match synkroniserer: Henter certificates og profiles fra Git-repoet. I CI kjorer den readonly (oppretter aldri nye).
  3. Build: Xcode bruker provisioning profile fra Match for a signere appen.

Beta lane i detalj

heading.anchorLabel

Nar fastlane ios beta kjorer, skjer dette:

  1. Sjekk clean git (skippes i CI)
  2. Sync signing — henter sertifikater via Match
  3. Auto-inkrement build number — henter siste fra TestFlight, legger til 1
  4. KMP release frameworklinkReleaseFrameworkIosArm64
  5. Archive — release-build med export_method: "app-store"
  6. Upload til TestFlight — med changelog fra siste 15 commits
  7. Commit versjonsbump + tagbeta/v1.2.3-42

8. Git Workflow

heading.anchorLabel

Branch-basert flyt

heading.anchorLabel
feature/* ──> Pull Request ──> main ──────────────> production
(utvikling) (CI kjorer) (-> staging auto) (/deploy-prod)
iOS: fastlane ios bump ──> git tag v* ──> TestFlight ──> App Store
(/release ios) (auto) (/promote)

Branch-navnkonvensjoner

heading.anchorLabel
PrefiksBrukEksempel
feat/Ny funksjonalitetfeat/check-in-flow
fix/Bugfixfix/session-timeout
chore/Vedlikehold, oppryddingchore/update-deps
refactor/Kode-omstruktureringrefactor/store-architecture
docs/Dokumentasjondocs/cicd-guide

Commit-meldinger

heading.anchorLabel

Folg Conventional Commits-monsteret:

feat(ios): add check-in flow with AI coaching
fix(api): cap breakthroughs to meaningful clusters
chore: update AI prompts and dashboard cleanup
refactor(shared): simplify impulse classification model
docs: add CI/CD complete guide

Format: <type>(<scope>): <beskrivelse>

Branch Protection

heading.anchorLabel
  • CI Gate required: PR kan ikke merges med mindre CI Gate er gronn
  • Aldri push direkte til main: All kode gar via PR
  • Squash merge anbefalt: Holder commit-historikken ren

9. Claude Code Integration

heading.anchorLabel

Claude Code har innebygde kommandoer som mapper til CI/CD-pipelinen:

KommandoHva den gjorMapper til
/deploy-prodPromoterer staging til productiongit push origin main:production
/release ios [patch|minor|major]iOS versjonsbump + TestFlightfastlane ios bump + git tag v*
/promotePromoterer TestFlight-bygg til App Storefastlane ios promote
/deploy-statusViser status pa siste deploysgh run list
/prOppretter PR med sammendragGitHub PR + trigger CI

10. Daglig arbeidsflyt — Steg for steg

heading.anchorLabel

Morgen: Sjekk status

heading.anchorLabel
Terminal window
# Sjekk om noe har feilet i natt
gh run list --limit 5
# Eller via Claude Code
/deploy-status

Under dagen: Feature-utvikling

heading.anchorLabel
  1. Lag feature branch

    Terminal window
    git checkout -b feat/min-nye-feature
  2. Utvikle og commite

    Terminal window
    # Jobb pa koden...
    git add -A
    git commit -m "feat(ios): add awesome feature"
  3. Push og la CI gjore jobben

    Terminal window
    git push -u origin feat/min-nye-feature
    # CI starter automatisk

Klar for merge

heading.anchorLabel
  1. Opprett PR

    Terminal window
    # Via Claude Code
    /pr
    # Eller manuelt
    gh pr create --fill
  2. Vent pa CI Gate — gronn checkmark i GitHub

  3. Merge til main -> staging deployes automatisk

Klar for production (DB + API)

heading.anchorLabel
  1. Verifiser at staging fungerer

    Terminal window
    # Sjekk staging-deploy
    gh run list --branch main --limit 3
  2. Promoter til production

    Terminal window
    # Via Claude Code:
    /deploy-prod
    # Eller manuelt:
    git push origin main:production
  3. Verifiser production — sjekk Railway logs og API-respons

iOS-release (separat syklus)

heading.anchorLabel
  1. Bump versjon og send til TestFlight

    Terminal window
    cd apps/mobile-kmp/iosApp
    bundle exec fastlane ios bump type:patch
    # Git tag v* opprettes automatisk -> TestFlight-bygg starter
  2. Test pa TestFlight — appen dukker opp etter 15-30 min

  3. Promoter til App Store

    Terminal window
    cd apps/mobile-kmp/iosApp
    bundle exec fastlane ios promote
  4. Submit for review i App Store Connect (manuelt steg)


11. Feilsoking

heading.anchorLabel

Nar CI feiler

heading.anchorLabel

Database-sjekk feiler

heading.anchorLabel

Vanligste arsak: Genererte typer er utdaterte.

Terminal window
# Fix: Regenerer types lokalt og commit
pnpm db:types
git add packages/database/types/database.ts
git commit -m "chore: update generated database types"

API-sjekk feiler

heading.anchorLabel

Vanligste arsaker: TypeScript type errors, lint-feil, testfeil.

Terminal window
# Kjor lokalt for a reprodusere
pnpm --filter api lint
pnpm --filter api type-check
pnpm --filter api test

iOS preflight feiler

heading.anchorLabel

Vanligste arsaker: KMP kompileringsfeil, Xcode build-feil.

Terminal window
# Rask KMP-sjekk lokalt
cd apps/mobile-kmp
./gradlew :shared:compileKotlinIosSimulatorArm64
# Full preflight
cd iosApp
bundle exec fastlane ios preflight

Nar deploy feiler

heading.anchorLabel

Database-migrasjon feiler i staging/production

heading.anchorLabel
  1. Sjekk loggen i GitHub Actions for a se den eksakte feilen
  2. Kjor dry-run via manuell workflow: Actions -> “DB Deploy (manual)” -> velg miljo -> “dry-run”
  3. Fiks migrasjonsfilen lokalt, test med pnpm db:reset
  4. Commit og push — CI + staging deploy kjorer pa nytt

iOS TestFlight-upload feiler

heading.anchorLabel
  1. Sjekk signing: Er Match-sertifikatene gyldige? Kjor fastlane ios doctor
  2. Sjekk Doppler: Er ASC_KEY_ID, ASC_ISSUER_ID, ASC_PRIVATE_KEY satt for prd?
  3. Timeout? Build har 30 min timeout. Sjekk om Gradle-cache mangler.
  4. Force retry: Actions -> “iOS Release (manual)” -> velg “beta”

Railway deployer ikke

heading.anchorLabel

Railway overvaker branchen direkte. Hvis den ikke deployer:

  • Sjekk Railway dashboard for feilmeldinger
  • Verifiser at Railway staging er koblet til main-branchen
  • Verifiser at Railway production er koblet til production-branchen
  • Sjekk at Doppler-secrets er synkronisert til Railway via integrasjonen (stg -> staging, prd -> production)

Sjekke logger

heading.anchorLabel
Terminal window
# Se siste workflow-kjoringer
gh run list --limit 10
# Se detaljer for en spesifikk kjoring
gh run view <run-id>
# Se logger for en feilet jobb
gh run view <run-id> --log-failed

Manuelle fallback-workflows

heading.anchorLabel
WorkflowHvaNar
db-deploy.ymlManuell DB-migrasjon (dry-run eller migrate) mot staging/productionFeilretting, force-migrate, inspeksjon
ios-release.ymlManuell iOS-build (beta/promote/release)Force-release, promote til App Store

12. Nokkelfiler

heading.anchorLabel

Workflow-filer (GitHub Actions)

heading.anchorLabel
FilTriggerBeskrivelse
.github/workflows/ci.ymlPush/PR til mainHoved-CI: change detection, parallelle sjekker (DB, API, iOS, Android), CI Gate, staging deploy
.github/workflows/deploy-production.ymlPush til production branchProduction deploy: DB-migrasjoner + API deploy
.github/workflows/ios-release.ymlManuellFallback for iOS: beta (force), promote (TestFlight -> App Store), full release
.github/workflows/db-deploy.ymlManuellFallback for DB: dry-run eller migrate mot staging/production

Konfigurasjonsfiler

heading.anchorLabel
FilBeskrivelse
doppler.yamlLokal Doppler-konfig — kobler prosjektet til “im” med “dev” config
apps/mobile-kmp/iosApp/fastlane/FastfileAll iOS build-logikk: preflight, test, beta, promote, release, bump, doctor
apps/mobile-kmp/iosApp/GemfileRuby-avhengigheter for Fastlane
packages/database/supabase/Supabase-konfig og migrasjonsfiler

GitHub Secrets (konfigurert i repo Settings)

heading.anchorLabel
SecretBrukes iBeskrivelse
DOPPLER_TOKEN_STGCI + staging deployDoppler service token for staging-config
DOPPLER_TOKEN_PRDProduction deployDoppler service token for production-config

Sist oppdatert: Mars 2026