Skip to content

Feat: workflow integration test#1686

Open
pandigresik wants to merge 21 commits into
rilis-devfrom
feat/workflow_integration_test
Open

Feat: workflow integration test#1686
pandigresik wants to merge 21 commits into
rilis-devfrom
feat/workflow_integration_test

Conversation

@pandigresik

@pandigresik pandigresik commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Pull Request: feat: GitHub Actions Integration Regression Pipeline

Description

Menambahkan GitHub Actions workflow (integration-regression.yml) yang menjalankan rangkaian pengujian otomatis untuk mencegah regresi integrasi antara OpenDK (provider) dan OpenSID (consumer). Pipeline mencakup lint → unit tests → generate/validate OpenAPI → contract tests → integration tests → E2E bersyarat, beserta upload coverage ke Codecov dan coverage gate threshold.

Changes made:

  1. Feature: Added .github/workflows/integration-regression.yml — GitHub Actions workflow dengan 8 jobs: lint, unit, generate-openapi, contract, integration, e2e, coverage-gate, ci-summary
  2. Feature: Added bin/check-coverage.php — Script PHP untuk coverage threshold gate (min 30%, drop max 2%)
  3. Feature: Added bin/detect-flaky-tests.php — Script PHP untuk deteksi flaky tests dari laporan JUnit XML
  4. Config: Added pint.json — Laravel Pint configuration untuk menonaktifkan rules yang terlalu ketat
  5. Config: Updated phpunit.xml — Added Contract testsuite and clover coverage logging

Reason for change:

  • Regresi Tak Terdeteksi: Tanpa CI pipeline terpadu, perubahan kode dapat memecah integrasi tanpa disadari oleh pengembang
  • Contract Testing: OpenDK sebagai provider API perlu memastikan spesifikasi OpenAPI tetap kompatibel dengan consumer (OpenSID)
  • Coverage Gate: Mencegah penurunan kualitas kode secara gradual dengan threshold yang terukur
  • Flaky Test Detection: Mengidentifikasi test yang tidak stabil sebelum menjadi masalah kronis

Impact of change:

Quality Assurance: Semua PR otomatis diuji secara komprehensif sebelum merge
Early Detection: Regresi integrasi terdeteksi sejak awal, bukan saat deployment
Coverage Tracking: Codecov integration memberikan visibilitas tren coverage dari waktu ke waktu
Developer Experience: CI summary dengan test durations dan flaky test detection membantu debugging
Gated E2E: E2E tests hanya berjalan saat push ke master atau label run-e2e, menghemat waktu CI

Related Issue

#1676

Steps to Reproduce

Before (no CI pipeline):

  1. Developer membuat perubahan kode
  2. Tidak ada automated testing yang berjalan
  3. ❌ Regresi integrasi baru terdeteksi saat deployment ke production
  4. ❌ Tidak ada coverage tracking atau flaky test detection

After (with CI pipeline):

  1. Developer membuat perubahan kode dan push ke branch
  2. PR dibuka ke master, rilis-dev, dev, atau bug-fix
  3. ✅ Pipeline otomatis berjalan: lint → unit → openapi → contract → integration
  4. ✅ Coverage di-upload ke Codecov, gate check berjalan
  5. ✅ E2E berjalan dikondisikan (label run-e2e atau push ke master)
  6. ✅ CI summary menampilkan status semua jobs dan flaky test detection

Testing on related features:

  • Lint check (Laravel Pint) ✅ Working
  • Unit tests dengan coverage ✅ Working
  • OpenAPI spec generation & validation ✅ Working
  • Contract tests (consumer vs provider) ✅ Working
  • Integration tests dengan coverage ✅ Working
  • E2E tests (bersyarat) ✅ Working
  • Coverage gate threshold check ✅ Working
  • Flaky test detection ✅ Working

Checklist

  • I have complied with script writing rules
  • I have followed pull request review process
  • I have created automated tests to verify the pipeline
  • Manual testing has been done in development environment
  • No console errors or warnings
  • Code has been reviewed by team

Technical Details

Technical Explanation

Pipeline dibangun dengan arsitektur DAG (Directed Acyclic Graph) untuk parallelisasi yang optimal:

lint ──────────────────────────────────────┐
unit (coverage) ───────────────────────────┤
                                           ├──→ coverage-gate
generate-openapi ──→ contract ─────────────┤
                                           ├──→ e2e (bersyarat)
integration (coverage) ────────────────────┘

Job Details:

Job Timeout Dependencies Coverage
lint 5 min none no
unit 5 min none pcov
generate-openapi 10 min none no
contract 5 min generate-openapi no
integration 15 min none pcov
e2e 20 min lint, unit, contract, integration no
coverage-gate 5 min unit, integration no
ci-summary 5 min all no

Key Features:

  1. Composer cachingactions/cache@v4 dengan key berbasis composer.lock hash
  2. MySQL for all tests — Service container MySQL 8.0 untuk unit dan integration tests (kompatibel dengan semua kolom MySQL)
  3. php artisan test --testsuite — Menggunakan PHPUnit's testsuite filtering (bukan Pest groups) untuk menghindari loading Browser/Playwright
  4. php artisan migrate --force — Semua job menjalankan migrasi sebelum test untuk memastikan struktur database valid
  5. Scribe OpenAPI generation — Menggunakan MySQL service untuk generate spec lengkap
  6. Coverage thresholdsCOVERAGE_MIN_THRESHOLD: 30 dan COVERAGE_DROP_THRESHOLD: 2 (baseline, naikkan bertahap)
  7. Artifact retention — Coverage (7 hari), OpenAPI spec (14 hari), Playwright report (14 hari)
  8. Laravel Pint configurationpint.json menonaktifkan rules yang terlalu ketat sehingga CI lint check lebih realistis

Coverage Gate Script (bin/check-coverage.php):

  • Parses Clover XML files (unit + integration)
  • Uses integration coverage as primary gate metric
  • Checks minimum threshold (default 30%, naikkan bertahap)
  • Checks drop threshold against COVERAGE_PREV env var (default 2%)
  • Outputs results to GITHUB_STEP_SUMMARY
  • Exit codes: 0 (pass), 1 (below min), 2 (drop exceeded), 3 (parse error)

Coverage Threshold Strategy:

  • Baseline: 30% (coverage saat ini ~32.61%)
  • Target: Naikkan 5% tiap quarter
  • Formula: MIN_THRESHOLD = current_coverage - buffer (2-5%)

Flaky Test Detection Script (bin/detect-flaky-tests.php):

  • Parses JUnit XML reports from all test suites
  • Heuristics: failures, slow tests (>5x median), zero-duration, skipped
  • Calculates median/mean test durations
  • Outputs report to GITHUB_STEP_SUMMARY
  • Exit code 1 if > 5 failures (systemic issue indicator)

Configuration changes

  • phpunit.xml: Added Contract testsuite (clover logging via CLI option)
  • pint.json: Laravel Pint configuration untuk menonaktifkan rules yang terlalu ketat
  • config/scribe.php: Tidak ada perubahan (frontend routes prefix sudah di-inherit dari base branch)

Dependencies added

  • No new Composer dependencies
  • GitHub Actions used:
    • actions/checkout@v4
    • actions/cache@v4
    • actions/upload-artifact@v4
    • actions/download-artifact@v4
    • shivammathur/setup-php@v2
    • actions/setup-node@v4
    • codecov/codecov-action@v4

Testing

Manual Testing

  • Workflow YAML valid (GitHub Actions lint)
  • Lint job runs successfully with Pint
  • Unit tests run with MySQL service
  • OpenAPI spec generates correctly with MySQL
  • Contract tests pass against generated spec
  • Integration tests run with MySQL service
  • E2E tests dikondisikan oleh label run-e2e
  • Coverage gate checks threshold correctly
  • CI summary generates with all job statuses
  • Flaky test detection analyzes JUnit reports

Automated Testing

  • Unit Test: Existing test suite passes
  • Integration Test: Existing test suite passes
  • Contract Test: OpenAPI spec validation passes

Browser Compatibility

Not applicable — CI pipeline configuration only

Screenshots / Video

No UI changes — this is a CI/CD configuration PR

Breaking Changes

None

Migration Guide

Required GitHub Secrets

Add the following secrets to repository settings:

Secret Description Required
CODECOV_TOKEN Codecov upload token Yes (for coverage)
E2E_ADMIN_EMAIL Admin email for E2E tests Optional (for E2E)
E2E_ADMIN_PASSWORD Admin password for E2E tests Optional (for E2E)

Optional Configuration

Environment variables in workflow can be customized:

env:
  PHP_VERSION: "8.4"           # PHP version for all jobs
  NODE_VERSION: "20"           # Node.js version for E2E
  COVERAGE_MIN_THRESHOLD: 30   # Minimum coverage % (baseline, naikkan bertahap)
  COVERAGE_DROP_THRESHOLD: 2   # Max allowed coverage drop %

Developer Workflow

  1. Normal PR: Lint + Unit + Contract + Integration run automatically
  2. With E2E: Add label run-e2e to PR, or push to master
  3. Coverage: Uploaded to Codecov with flags (unit, integration, combined)
  4. Debugging: Check CI Summary job for test durations and flaky test report

References


Additional notes:

  • Pipeline dirancang untuk parallelisasi maksimal: lint, unit, generate-openapi, dan integration berjalan bersamaan
  • Unit tests menggunakan MySQL (bukan SQLite) untuk menghindari inkompatibilitas kolom MySQL
  • php artisan test --testsuite digunakan daripada vendor/bin/pest --group untuk menghindari loading Playwright
  • Semua job menjalankan php artisan migrate --force sebelum test untuk memastikan struktur database valid
  • Semua job membuat build/logs directory sebelum test untuk memastikan coverage file ter-generate
  • Coverage di-generate via --coverage-clover CLI option (bukan via phpunit.xml clover element)
  • E2E tests dikondisikan untuk menghemat waktu CI (hanya berjalan saat dibutuhkan)
  • Coverage gate menggunakan integration coverage sebagai primary metric karena lebih komprehensif
  • Coverage threshold di-set ke 30% sebagai baseline (coverage saat ini ~32.61%), naikkan bertahap
  • Semua Codecov upload menggunakan fail_ci_if_error: false untuk mencegah CI gagal saat token belum di-set
  • Codecov token (CODECOV_TOKEN) perlu di-set di GitHub repository secrets untuk branch protected
  • Flaky test detection menggunakan heuristik sederhana (5x median) yang dapat ditingkatkan di masa depan
  • pint.json menonaktifkan rules seperti trailing_comma_in_multiline, fully_qualified_strict_types, not_operator_with_successor_space, dll yang terlalu ketat untuk codebase yang sudah ada
  • Semua artifacts di-upload dengan retention period yang sesuai (7-14 hari)

Cara Meningkatkan Coverage:

  1. Jalankan coverage report lokal:

    php artisan test --testsuite=Unit --coverage-text
    php artisan test --testsuite=Feature --coverage-text
  2. Prioritas test berdasarkan impact:

    Prioritas Target Effort
    1 Models (relationship, scope, accessor) Mudah
    2 Services (business logic) Sedang
    3 Controllers (HTTP response, validation) Sedang
    4 Routes (access control) Mudah
  3. Contoh test sederhana:

    // tests/Unit/Models/ArtikelTest.php
    test('artikel has relationship with kategori', function () {
        $artikel = Artikel::factory()->create();
        expect($artikel->kategori)->not->toBeNull();
    });
    
    test('artikel scope active only returns active articles', function () {
        Artikel::factory()->create(['status' => 1]);
        Artikel::factory()->create(['status' => 0]);
        expect(Artikel::active()->count())->toBe(1);
    });
  4. Naikkan threshold bertahap:

    • Baseline: 30% (sekarang)
    • Q2: 35%
    • Q3: 40%
    • Q4: 50%

- Update config/scribe.php with proper auth, routes, and OpenAPI config
- Add artisan command scribe:copy-openapi to copy spec to repo root
- Add composer scripts: generate-openapi, validate-openapi
- Add openapi.yaml (initial generated spec with 54 endpoints)
- Add CI workflow: openapi.yml (generate & validate on PR/push)
- Update test.yml to also copy & validate OpenAPI spec
- Add docs/integration-testing.md with local dev instructions
- Add SCRIBE_AUTH_KEY to .env.example
- Fix CekDesa rule: lazy-load DB query in message() instead of constructor
- Add missing test() method to PendudukController
- Regenerate openapi.yaml (now 61 paths, covering all api.php routes)
- Remove outdated note about missing endpoints from docs
- Add @group and @bodyParam/response annotations to all api/v1 controllers
- Add meaningful summaries to frontend API controllers
- Fix AuthController login with proper Scribe annotations
- Regenerate openapi.yaml with all 61 paths properly described
- Each OpenSID submission endpoint now has documented body params & response
- Remove api/frontend/* from scribe route prefixes
- Regenerate spec: 21 paths, focused on OpenSID endpoints only
- Add detailed ZIP column contracts to controller docblocks
- Separate JSON vs ZIP endpoints with proper @bodyParam types
- Add ZIP contract validation table to docs/integration-testing.md
- Add sample ZIP generator script and Pest contract test example
- Each file upload endpoint now documents expected internal file format
- Add Pest-based contract tests validating 11 request payloads vs OpenAPI spec
- Create example JSON payloads for auth, penduduk, laporan, pesan, identitas-desa
- Add contract.yml CI workflow (no DB needed, runs on PR to master/dev)
- Fix laporan_apbdes & laporan_penduduk controller annotations for proper object[] schema
- Add composer test:contract and npm run test:contract scripts
- Document running contract tests locally in docs/integration-testing.md

Issue: #1673
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI PR Review sedang antri di server...

Proses review akan segera dimulai di background — hasil akan muncul sebagai komentar setelah selesai.
Powered by CrewAI · PR #1686

@pandigresik
pandigresik requested a review from vickyrolanda July 21, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant