first commit

This commit is contained in:
2026-10-09 02:35:14 +07:00
commit 4ca7a9a58e
108 changed files with 23035 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
# A1 (R18) — verifikasi pin sqlalchemy<2.1 tidak menggeser paket
# tanggal : 2026-10-01 21:04:37
# metode : uv pip compile requirements.in --constraint <lock lama>
# base : apache/airflow:slim-3.3.1-python3.11
# lock lama : 1188 baris · md5 5936cf19f36004fd
# lock baru : 1650 baris
# baris PAKET berbeda : 0
# sqlalchemy : sqlalchemy==2.0.54 -> sqlalchemy==2.0.54
#
# KESIMPULAN
# 0 paket berubah — pin ini PREVENTIF (mencegah regenerasi lock mendatang
# menarik SQLAlchemy 2.1). Lock dibiarkan utuh karena isi paketnya identik;
# perbedaannya hanya baris komentar anotasi constraint (-c /old.lock).
# Perlindungan ada di requirements.in (sumber), bukan di lock.
+114
View File
@@ -0,0 +1,114 @@
# Hasil Uji B3 — Titik Go/No-Go BATCH B (review R18)
> **Tanggal**: 2026-10-01 · **Image diuji**: `sicabe/airflow:3.3.2-om203-py313` (ID `33990a6c2b88`)
> **Metode**: stack eksperimen terisolasi (`airflow332-exp`, port 12184/12185) + config & DAG
> produksi di-mount **read-only** + uji koneksi/OPA/dbt dari container sekali pakai.
> ⚠️ Produksi **tidak tersentuh** sepanjang uji.
---
## 1. VERDICT: 🔴 **NO-GO untuk Python 3.13**
BATCH B **tidak boleh dilanjutkan** dengan base Python 3.13. Penyebab tunggal: **dbt tidak
berfungsi** di Python 3.13 pada tumpukan dependensi kita — dan dbt adalah tulang punggung
lapisan silver/gold.
**Yang tetap sahih**: seluruh hasil B3 lainnya, serta A1 (pin `sqlalchemy<2.1`), A2, dan B1.
**Yang perlu diulang**: hanya **B2** (build image) dengan base Python **3.11**.
---
## 2. Yang LOLOS ✅
| Uji | Hasil |
|---|---|
| **DAG produksi (4 berkas, dari volume produksi)** | ✅ `dag_sitomat_gold_build.py`, `dag_sitomat_gold_build_prod.py` **impor bersih**. `sicabe_dq_gold_native.py` berhasil dimuat sampai tahap *generate workflow* (gagal hanya karena `openmetadata-server` tidak ter-resolve dari container uji saya — bukan masalah versi) |
| **Plugin OpenMetadata** | ✅ `/pluginsv2/api/v2/openmetadata/health-auth` → **200**; `/pluginsv2/` → **200** |
| **Trino** | ✅ `SELECT 1` → `[[1]]`; `SHOW TABLES FROM iceberg.bronze` → `orders`, `orders_incremental` |
| **MinIO** | ✅ bucket `['iceberg-data']` via `S3Hook` |
| **MySQL (klien eksternal)** | ✅ `('8.0.40', 'asdp')` via `MySQLdb`/`MySqlHook` |
| **PostgreSQL** | ✅ Postgres 15.18 via `PostgresHook` |
| **OPA** | ✅ aturan bronze utuh (`bronze_orders`: ddl/select/write) + keputusan INSERT bronze = **true** |
| **Metadata DB / migrasi** | ✅ `airflow db migrate` bersih; OM 2.0.3 (API `{"version":"2.0.3"}`) |
---
## 3. Yang GAGAL 🔴 — dbt
### 3.1 Gejala
```
$ dbt debug --profile trino --target prod
AttributeError: __class_getitem__
mashumaro/core/meta/helpers.py:624 → typing_extensions.Annotated.__class_getitem__
/usr/python/lib/python3.13/typing.py:548
```
`dbt compile` gagal dengan galat yang sama.
⚠️ **`dbt --version` justru berhasil** — sehingga pemeriksaan dangkal (`import dbt`,
`dbt --version`) **tidak menangkap** kerusakan ini.
### 3.2 Akar masalah & tiga versi yang diuji
| `mashumaro` | dbt (`debug`/`compile`) | `pip check` |
|---|---|---|
| **3.10** (maksimum yang diizinkan `collate-data-diff <3.11`) | ❌ **GAGAL** | ✅ **bersih** ← *rusak, tapi terlihat sehat* |
| **3.17** | ✅ **debug OK ("All checks passed!") + compile OK** (SQL `orders_silver` ter-compile) | ⚠️ melanggar `dbt-core <3.15` **dan** `collate-data-diff <3.11` |
| **3.23** | ✅ berhasil | ⚠️ melanggar keduanya |
### 3.3 Kesimpulan teknis
**Tidak ada versi `mashumaro` yang sekaligus (a) memenuhi batas dependensi kita dan
(b) berfungsi di Python 3.13.** Yang mengikat ketat adalah `collate-data-diff` (dipakai jalur
lineage dbt OpenMetadata) yang menuntut `<3.11.0`, sedangkan perbaikan kompatibilitas 3.13
berada di versi ≥ ~3.11.
➡️ Jadi masalahnya bukan pilihan paket, melainkan **kombinasi Python 3.13 + tumpukan ini**.
### 3.4 Pelajaran metodologis (penting)
`pip check` **bersih** pada konfigurasi yang **tidak berfungsi**. Artinya:
> Batas dependensi yang dideklarasikan ≠ kebenaran fungsional.
Uji kelayakan untuk tumpukan ini **wajib menjalankan perintah nyata** (mis. `dbt debug`,
`dbt compile`), bukan hanya mengimpor modul atau membaca `--version`.
---
## 4. Koreksi atas rekomendasi K1
Rekomendasi awal saya (K1 = Python **3.13**) dinilai **salah** dan dicabut. Dasarnya waktu itu
adalah "artefak eksperimen sudah tervalidasi end-to-end" — padahal validasi itu **tidak
lengkap**: eksperimen memeriksa `import dbt` dan `dbt --version`, tetapi **tidak pernah
menjalankan `dbt` sungguhan**. B3 — yang memang dirancang sebagai gerbang — yang menemukannya.
**K1 direvisi menjadi Python 3.11**, dengan alasan:
- tujuan BATCH B adalah **Airflow 3.3.2 + OM 2.0.3 + provider MySQL**, bukan Python 3.13;
- `openmetadata-ingestion[airflow]` 2.0.3.0 mem-pin `apache-airflow==3.3.2` **terlepas dari
Python** → 3.3.2 di Python 3.11 tetap koheren;
- Python 3.11 mempertahankan seluruh dependensi lain di set yang **sudah terbukti di produksi**
→ risiko jauh lebih rendah.
---
## 5. Langkah berikutnya (B2 revisi)
| Sub | Isi |
|---|---|
| B2r.1 | `Dockerfile.332` → base `slim-3.3.2-python3.11` (stage builder `mysqlclient` disesuaikan dengan kondisi header Python 3.11 pada base itu) |
| B2r.2 | Regenerasi lock 3.3.2/py3.11 **dengan lock 3.3.1 sebagai `--constraint`** (platform identik → diff minimal; teknik yang terbukti di A1) |
| B2r.3 | Build ulang image (tag tetap `sicabe/airflow:3.3.2-om203-py313`, menimpa image yang no-go) |
| B3r | **Ulangi B3 dengan `dbt debug` + `dbt compile` sebagai syarat WAJIB** (bukan opsional) |
---
## 6. Catatan kesalahan uji saya (agar tidak terulang)
| # | Kesalahan | Akibat |
|---|---|---|
| 1 | Memakai `airflow dags list` untuk menguji folder yang di-mount | `dags list` membaca **metadata DB**, bukan folder → uji pertama tidak sah (diperbaiki dengan impor langsung tiap berkas DAG) |
| 2 | Menguji DAG dari container yang tidak berada di jaringan yang tepat | `openmetadata-server` tidak ter-resolve → kegagalan palsu |
| 3 | Mount dbt **read-only** | dbt perlu menulis `logs/` → keluar `exit 2` **tanpa keluaran sama sekali** (menyesatkan) |
| 4 | `pip install "mashumaro>=3.9,<3.18"` tanpa `--upgrade` | pip tidak menaikkan (3.10 sudah memenuhi rentang) → uji sempat tidak konklusif |
| 5 | Salah mount point volume config OM | kegagalan palsu pada DAG DQ |
| 6 | Pemeriksaan awal hanya `import dbt` / `dbt --version` | kerusakan dbt lolos sampai B3 |
+72
View File
@@ -0,0 +1,72 @@
# Hasil B3 ULANG — Go/No-Go BATCH B pada Image Python 3.11 (review R18)
> **Tanggal**: 2026-10-01 · **Image diuji**: `sicabe/airflow:3.3.2-om203` (ID `a02620e1d0a8`)
> — hasil **B2 revisi** (base Python 3.11), menggantikan image py3.13 yang ditolak.
> **Metode**: sama dengan B3 pertama — stack eksperimen terisolasi + config & DAG produksi
> read-only + container sekali pakai untuk koneksi/dbt. ⚠️ Produksi tidak tersentuh.
---
## 1. VERDICT: 🟢 **GO**
BATCH B boleh dilanjutkan ke B4. Penyebab no-go sebelumnya (dbt mati di Python 3.13)
**teratasi** dengan kembali ke Python 3.11.
---
## 2. Hasil lengkap
| # | Uji | Hasil |
|---|---|---|
| 1 | `airflow version` | ✅ **3.3.2** |
| 2 | **`dbt debug`** | ✅ **"Connection test: OK connection ok" + "All checks passed!"** |
| 3 | **`dbt compile --select orders_silver`** | ✅ compiles (SQL model terbentuk) |
| 4 | DAG produksi `dag_sitomat_gold_build.py` | ✅ impor bersih |
| 5 | DAG produksi `dag_sitomat_gold_build_prod.py` | ✅ impor bersih |
| 6 | DAG `sicabe_dq_gold_native.py` | ✅ dimuat sampai tahap *generate workflow*; gagal hanya karena `openmetadata-server` tidak ter-resolve dari container uji (bukan masalah versi) |
| 7 | `airflow dags list-import-errors` | ✅ kosong |
| 8 | Plugin OM `/pluginsv2/api/v2/openmetadata/health-auth` | ✅ **HTTP 200** |
| 9 | Plugin OM `/pluginsv2/` | ✅ **HTTP 200** |
| 10 | Trino (`TrinoHook`) | ✅ `SELECT 1` → `[[1]]`; bronze: `orders`, `orders_incremental` |
| 11 | MinIO (`S3Hook`) | ✅ bucket `['iceberg-data']`, `check_for_bucket` True |
| 12 | MySQL klien eksternal (`MySqlHook`) | ✅ `('8.0.40', 'asdp')`; tabel `passenger_productions`, `trx_booking` |
| 13 | OPA (aturan bronze `data-engineer`) | ✅ utuh (`bronze_orders`: ddl/select/write) |
Verifikasi dari **build** (step #18–#24): 5 klien DB, `mysqlclient` C termuat +
`libmariadb.so.3`, provider mysql, `dbt + great_expectations`, `flask_appbuilder` +
**plugin OM dapat dimuat** (`RestApiPlugin`), `pip check` bersih.
---
## 3. Ringkasan perjalanan B2 (tiga percobaan)
| Percobaan | Masalah | Penyelesaian |
|---|---|---|
| **1** | Build memakai Python 3.13 → **dbt mati** (mashumaro/Annotated) | Diputuskan pindah ke Python 3.11 (lihat `b3-hasil-uji.md`) |
| **2** | Build py3.11: pip install 62 menit (jaringan PyPI ~60–80 kB/s) lalu gagal di **penjaga regresi yang saya tulis** | Penjaga dipanggil dengan 1 argumen → `TypeError: Annotated[...] should be used with at least two arguments`. Diperbaiki menjadi `te.Annotated[int, 'meta']`. ⚠️ Galat itu justru membuktikan jalur Annotated **ada** di py3.11 |
| **3** | — | ✅ **BERHASIL** (langkah pip ter-cache → selesai cepat) |
Catatan operasional: build percobaan 1 sempat **dibatalkan** karena client `docker build`
ikut mati saat shell pengawas dihentikan (`nohup` tidak cukup — perlu `setsid`).
---
## 4. Konsekuensi & langkah berikutnya
- **Image target BATCH B**: `sicabe/airflow:3.3.2-om203` (ID `a02620e1d0a8`, 3.2 GB).
- Image py3.13 (`3.3.2-om203-py313`) **tidak dipakai** — disimpan sebagai bukti no-go.
- `Dockerfile.332` + `requirements.332.in/.lock` sudah final untuk py3.11; lock hanya
**44 baris** berbeda dari produksi.
- Berikutnya: **B4** — naikkan `AIRFLOW_IMAGE` + `OPENMETADATA_VERSION` di
`environment.defaults.sh` lalu `docker compose up -d`.
- Bukti rollback: `deploy/output/merge-airflow332-rollback.md` (dump sudah diuji pulih).
---
## 5. Kesalahan uji saya pada B3r (agar tidak terulang)
| # | Kesalahan | Akibat |
|---|---|---|
| 1 | Penjaga regresi `Annotated.__class_getitem__((int,))` — argumen kurang satu | **Positif palsu**: build gagal padahal sehat |
| 2 | Uji MinIO hanya meng-`source deploy/.env`, tanpa `environment.defaults.sh` | `MINIO_ROOT_USER` kosong → `NoCredentialsError` (bukan masalah image) |
| 3 | `pgrep -f` mencocokkan perintah saya sendiri | PID yang dilaporkan tidak sahih saat memantau build |
+178
View File
@@ -0,0 +1,178 @@
# Rollback — Merge Eksperimen `airflow332` ke `deploy/` (BATCH B / review R18)
> **Dibuat**: 2026-10-01 · **Oleh**: langkah **B1** dari `reviews/sicabe-18-merge-airflow332-plan.md`
> **Status**: 🟢 **Backup siap & TERBUKTI DAPAT DIPULIHKAN.** BATCH B **belum dijalankan**.
> ⚠️ **Berkas ini adalah satu-satunya jalan pulang** untuk langkah B4 (migrasi OpenMetadata
> bersifat **satu arah** — lihat `docs/sicabe-install-phases-detail.md` §8.11.2).
---
## 1. Keadaan yang dibekukan (baseline sebelum BATCH B)
| Item | Nilai |
|---|---|
| Tanggal baseline | 2026-10-01 |
| Airflow | **3.3.1** (`sicabe/airflow:3.3.1-om202`) |
| OpenMetadata | **2.0.2** (`openmetadata/server:2.0.2`) |
| OpenSearch | `opensearchproject/opensearch:3.8.0` |
| Gate `test-verification.sh` | **60 PASS / 0 FAIL / 2 SKIP** |
| Container produksi | 20 (Airflow webserver/scheduler/dag-processor, OM, OpenSearch, dst) |
---
## 2. Berkas backup
Lokasi: `deploy/output/merge-airflow332-backup/` — **gitignored** (berisi data produksi).
| Berkas | Isi | Ukuran | MD5 |
|---|---|---|---|
| `openmetadata_db.dump` | dump `openmetadata_db` (format `-Fc`) | 1.9 MB | `a8495339165cfbc286ea7e90490c12bb` |
| `airflow.dump` | dump `airflow` (format `-Fc`) | 248 KB | `4a834cc43307b296b58c250909749d2a` |
| `environment.defaults.sh.before-B` | salinan `deploy/config/environment.defaults.sh` | 22 KB | `2d341e008af43a7b` |
Ukuran DB saat baseline: `openmetadata_db` = **36 MB**, `airflow` = **12 MB**.
---
## 3. Bukti backup DAPAT DIPULIHKAN (dua kali diuji)
| Uji | Hasil |
|---|---|
| Restore `openmetadata_db` → DB coretan `_restorecheck_om` | **204 tabel** asli = **204 tabel** hasil restore ✅ |
| Restore `airflow` → DB coretan `_restorecheck_af` | **5 DAG** asli = **5 DAG** hasil restore ✅ |
| DB coretan setelah uji | dihapus ✅ (produksi tidak tersentuh: 20 container, OM HTTP 200) |
Perintah yang dipakai (nilai persis):
```bash
# contoh untuk openmetadata_db
docker exec -e PGPASSWORD=<dari deploy/.env> sicabe-postgres \
psql -U sicabe_admin -d postgres -c "CREATE DATABASE _restorecheck_om OWNER openmetadata;"
docker cp deploy/output/merge-airflow332-backup/openmetadata_db.dump sicabe-postgres:/tmp/check.dump
docker exec -e PGPASSWORD=<…> sicabe-postgres \
pg_restore -U sicabe_admin -d _restorecheck_om --no-owner --no-privileges /tmp/check.dump
docker exec -e PGPASSWORD=<…> sicabe-postgres \
psql -U sicabe_admin -d postgres -c "DROP DATABASE _restorecheck_om;"
```
---
## 4. Digest image (untuk kembali ke versi lama)
| Image | Image ID (sha256, dipotong) |
|---|---|
| `sicabe/airflow:3.3.1-om202` (produksi saat ini) | `afc0421a0490…` |
| `sicabe/airflow:3.3.1-om202-presqlalchemy` (tag rollback A1) | `afc0421a0490…` (identik — A1 tidak rebuild) |
| **`sicabe/airflow:3.3.2-om203`** (target BATCH B — Python 3.11, hasil B2 revisi) | `a02620e1d0a8…` (3.2 GB) |
| ~~`sicabe/airflow:3.3.2-om203-py313`~~ — **DITOLAK** di B3 (dbt mati di Python 3.13) | `33990a6c2b88…` (tidak dipakai) |
| `openmetadata/server:2.0.2` | `3b6f52aeb30f…` |
| `openmetadata/server:2.0.3` (target BATCH B) | `5f4d52bca2d7…` |
| `opensearchproject/opensearch:3.8.0` | `fafe3fc35870…` |
---
## 5. PROSEDUR ROLLBACK
### 5.1 Kasus paling umum — B4/B5 gagal, skema OM masih sehat
Cukup kembalikan versi, tanpa menyentuh DB:
```bash
cd /home/broto/sicabe-doc/deploy
# (1) kembalikan versi ke baseline
# AIRFLOW_IMAGE -> sicabe/airflow:3.3.1-om202
# OPENMETADATA_VERSION -> 2.0.2
# (atau pulihkan berkas utuh: cp output/merge-airflow332-backup/environment.defaults.sh.before-B \
# config/environment.defaults.sh)
# (2) jalankan ulang
docker compose up -d airflow-webserver airflow-scheduler airflow-dag-processor \
openmetadata-server openmetadata-migrate
# (3) verifikasi
./test-verification.sh # harapan: 60 PASS / 0 FAIL / 2 SKIP
```
### 5.2 Kasus berat — migrasi OM 2.0.3 merusak skema
⚠️ **Urutannya penting**: OM produksi harus **berhenti** dulu sebelum restore, kalau tidak
koneksi aktif akan mengganggu `DROP/CREATE DATABASE`.
```bash
cd /home/broto/sicabe-doc/deploy
# (1) HENTIKAN OpenMetadata (wajib, sebelum menyentuh DB-nya)
docker stop sicabe-openmetadata
# (2) pulihkan versi image di config (OPENMETADATA_VERSION=2.0.2)
cp output/merge-airflow332-backup/environment.defaults.sh.before-B config/environment.defaults.sh
# (3) restore openmetadata_db dari dump
docker exec -e PGPASSWORD=<dari deploy/.env> sicabe-postgres \
psql -U sicabe_admin -d postgres -c "DROP DATABASE IF EXISTS openmetadata_db;"
docker exec -e PGPASSWORD=<…> sicabe-postgres \
psql -U sicabe_admin -d postgres -c "CREATE DATABASE openmetadata_db OWNER openmetadata;"
docker cp output/merge-airflow332-backup/openmetadata_db.dump sicabe-postgres:/tmp/om.dump
docker exec -e PGPASSWORD=<…> sicabe-postgres \
pg_restore -U sicabe_admin -d openmetadata_db --no-owner --no-privileges /tmp/om.dump
# (4) mulai ulang dengan image LAMA
docker compose up -d openmetadata-server
# (5) verifikasi
curl -s http://localhost:12085/api/v1/system/version # harapan: {"version":"2.0.2",...}
```
### 5.3 Bila metadata Airflow perlu dipulihkan (mis. migrasi DB Airflow bermasalah)
```bash
docker stop sicabe-airflow-webserver sicabe-airflow-scheduler sicabe-airflow-dag-processor
docker exec -e PGPASSWORD=<…> sicabe-postgres psql -U sicabe_admin -d postgres \
-c "DROP DATABASE IF EXISTS airflow;" -c "CREATE DATABASE airflow OWNER airflow;"
docker cp output/merge-airflow332-backup/airflow.dump sicabe-postgres:/tmp/af.dump
docker exec -e PGPASSWORD=<…> sicabe-postgres \
pg_restore -U sicabe_admin -d airflow --no-owner --no-privileges /tmp/af.dump
docker compose up -d airflow-webserver airflow-scheduler airflow-dag-processor
```
### 5.4 Yang TIDAK perlu di-rollback
- **OpenSearch** — indeksnya **derived**: OM membangun ulang isinya. Tidak ada dump khusus
untuk itu, dan itu memang disengaja.
- **`deploy-legacy/`** — di luar lingkup (K6).
- **Image** — tidak dihapus; dua versi hidup berdampingan, jadi rollback hanya soal menunjuk
tag lama.
---
## 6. Setelah rollback
1. Catat penyebab kegagalan di berkas ini (bagian bawah) atau di `reviews/sicabe-18…`.
2. Jangan jalankan B4 lagi sebelum penyebabnya dipahami.
3. Indeks/tabel OM hasil migrasi yang tertinggal **tidak** dibiarkan: pastikan restore
benar-benar menggantikan `openmetadata_db` (bukan menumpuk).
---
## 7. Catatan keamanan
⚠️ Berkas dump berisi **data produksi** (termasuk baris `user_entity` — hash kredensial, dan
mungkin data pribadi). Perlakuan:
- **gitignored** (`deploy/output/merge-airflow332-backup/`) — jangan pernah di-commit;
- hapus setelah BATCH B dinyatakan stabil (dan simpan hanya bila memang diperlukan sebagai
arsip, di lokasi terbatas akses).
---
## Riwayat
| Tanggal | Kejadian |
|---|---|
| 2026-10-01 | B1 dijalankan: dump dibuat, **diuji pulih (204=204 tabel; 5=5 DAG)**, digest & config dicatat, dokumen ini dibuat. BATCH B belum dimulai. |
| 2026-10-01 | **B2** dijalankan: image `sicabe/airflow:3.3.2-om203-py313` dibangun **dari `deploy/`** (berdampingan — `Dockerfile.332` + `requirements.332.{in,lock}`), ID `33990a6c2b88…`. Seluruh verifikasi fatal lolos: 5 klien DB, `mysqlclient` benar-benar termuat, `sqlalchemy 2.0.54` (pin A1), **plugin OM dapat dimuat**, `pip check` bersih. Produksi **tetap** `3.3.1-om202` — belum tersentuh. |
| 2026-10-01 | **B3 (go/no-go) = NO-GO** untuk Python 3.13: `dbt debug`/`dbt compile` gagal (mashumaro → `Annotated.__class_getitem__`). Tidak ada versi `mashumaro` yang memenuhi batas dependensi kita **dan** berfungsi di 3.13. Bukti: `b3-hasil-uji.md` |
| 2026-10-01 | **B2 revisi**: base dikembalikan ke **Python 3.11**; lock di-resolve ulang dengan lock 3.3.1 sebagai constraint **tersaring** (`^apache-airflow`, `^openmetadata-`, `^collate-` dibuang) → hanya **44 baris** berbeda dari produksi. Image baru: **`sicabe/airflow:3.3.2-om203`** ID `a02620e1d0a8…` (3.2 GB) |
| 2026-10-01 | **B3 ULANG = GO** 🟢: `dbt debug` **"All checks passed"**, `dbt compile` OK, DAG produksi impor bersih, plugin `/pluginsv2/` **200**, Trino/MinIO/MySQL OK, OPA utuh. Bukti: `b3r-hasil-uji.md`. Produksi tetap `3.3.1-om202` — siap untuk **B4** |
| 2026-10-02 | **B4 dijalankan (produksi naik)**: migrasi OM 2.0.3 **exit 0**; `airflow-init` (DB migrate 3.3.2) **exit 0**; OM server + 3 service Airflow di-recreate ke versi baru — semuanya **healthy**. Image: `sicabe/airflow:3.3.2-om203`, `openmetadata/server:2.0.3` |
| 2026-10-02 | **B5 verifikasi = LOLOS** ✅: `airflow version` **3.3.2**; OM API **2.0.3**; plugin `/pluginsv2/…health-auth` **200**; **0 error impor** DAG; `MySQLdb` + provider mysql tersedia di produksi; **GATE 60 PASS / 0 FAIL / 2 SKIP** (identik baseline). **B6 (rollback) tidak diperlukan.** |
| — | ⚠️ **Dump DISIMPAN** sampai dinyatakan stabil. Bila beberapa hari produksi berjalan normal: hapus `deploy/output/merge-airflow332-backup/` (§7) — atau arsipkan di lokasi terbatas akses |
+114
View File
@@ -0,0 +1,114 @@
# Runbook Rollback — Integrasi OpenMetadata 2.0.2 ke `deploy/`
**Dibuat**: 2026-09-16 · **Tugas**: `merge-om20x` (subtask 01)
**Tag titik kembali**: `pre-merge-om20x` @ `5627353`
Runbook ini adalah dokumen yang ditulis tangan (bukan keluaran uji otomatis), sengaja
diletakkan di `deploy/output/` mengikuti penugasan subtask 01. Isinya harus tetap
akurat selama integrasi berlangsung.
---
## 1. Kapan runbook ini dipakai
Saat integrasi ke OpenMetadata 2.0.2 + OpenSearch 3.x + Airflow ber-plugin gagal dan
kita memutuskan kembali ke kondisi 1.13.1 yang stabil (sebelumnya gate Fase 1-6 hijau,
`test-verification.sh` = 60 PASS / 0 FAIL / 2 SKIP).
## 2. Kondisi baseline (terverifikasi sebelum perubahan apa pun)
| Aspek | Nilai |
|---|---|
| git HEAD | `5627353` (tag `pre-merge-om20x`) |
| OpenMetadata server | **1.13.1** (`openmetadata/server:1.13.1`) |
| OpenSearch | **2.19.6** (`opensearchproject/opensearch:2.19.6`) |
| Airflow image | **`sicabe/airflow:3.3.1-slim`** (id `15ae04b69228`), Airflow 3.3.1 |
| Plugin OpenMetadata di Airflow | **TIDAK ADA** — `/api/v1/openmetadata/health` → 404 |
| Data OM | database `openmetadata_db` di volume `sicabe_postgres-data` |
| Data OpenSearch | **tidak di volume** — ada di layer container (index derived) |
Catatan penting soal "plugin tidak ada": di Airflow deploy,
`/pluginsv2/api/v2/openmetadata/health-auth` menjawab **200 tetapi `content-type: text/html`**
(HTML aplikasi Airflow) — itu fallback UI, bukan respons plugin. Bukti plugin absen
adalah `/api/v1/openmetadata/health` → **404**. Jangan tertipu angka 200 di path
`/pluginsv2/`.
## 3. Cara memverifikasi kita benar-benar sudah kembali ke baseline
```bash
cd /home/broto/sicabe-doc
git rev-parse --short HEAD # harus 5627353 (atau turunannya yg setara)
docker inspect sicabe-openmetadata --format '{{.Config.Image}}' # openmetadata/server:1.13.1
docker inspect sicabe-opensearch --format '{{.Config.Image}}' # opensearchproject/opensearch:2.19.6
docker inspect sicabe-airflow-webserver --format '{{.Config.Image}}' # sicabe/airflow:3.3.1-slim
curl -s -o /dev/null -w '%{http_code}\n' -u "admin:$AIRFLOW_ADMIN_PASSWORD" \
http://localhost:12082/api/v1/openmetadata/health # harus 404
cd deploy && ./test-verification.sh # harus 60 PASS / 0 FAIL / 2 SKIP
```
## 4. Langkah rollback
### 4.1 Kembalikan berkas konfigurasi
```bash
cd /home/broto/sicabe-doc
git checkout pre-merge-om20x -- deploy/ docs/
git status -s # tinjau: hanya berkas deploy/docs yang kembali
```
Jangan `git reset --hard` — commit hasil eksperimen (`f47945d`, `5627353`) dan
`experiments/om20x/` tidak perlu ikut hilang.
### 4.2 Nyalakan ulang container lama
```bash
cd deploy
set -a && . ./.env && set +a
docker compose --profile all up -d --force-recreate \
openmetadata-opensearch openmetadata-migrate openmetadata-server \
airflow-init airflow-webserver airflow-scheduler airflow-dag-processor
```
Image lama **tidak boleh dihapus**: `openmetadata/server:1.13.1`,
`opensearchproject/opensearch:2.19.6`, `sicabe/airflow:3.3.1-slim`.
OpenSearch akan membuat index baru dari nol saat container dibuat ulang
(tidak ada volume; index memang derived dan OM akan mem-populasinya kembali).
### 4.3 Bila database OM sudah telanjur dikosongkan (subtask 12)
Setelah `openmetadata_db` di-drop, **data katalog OM tidak bisa dipulihkan dari
deploy** — tidak ada dump (keputusan sadar: jaring pengaman cukup tag git). Yang bisa
dilakukan: membuat ulang database kosong lalu membiarkan OM 1.13.1 membangun skemanya,
lalu mengisi ulang katalog dari sumber yang reproducible:
```bash
# buat ulang database kosong (pola sama dgn deploy/config/postgres/init/01-create-dbs.sh)
docker exec sicabe-postgres psql -U postgres -c "DROP DATABASE IF EXISTS openmetadata_db;"
docker exec sicabe-postgres psql -U postgres -c "CREATE DATABASE openmetadata_db OWNER openmetadata;"
cd deploy
docker compose --profile all up -d --force-recreate openmetadata-migrate # migrate schema 1.13.1
docker compose --profile all up -d openmetadata-server
./scripts/ingest-openmetadata.sh # katalog Trino + lineage dbt
# lalu jalankan DAG utk mengirim ulang hasil Great Expectations
```
## 5. Yang bisa dan tidak bisa dipulihkan (jujur)
| Bisa dipulihkan | Tidak bisa dipulihkan |
|---|---|
| Versi komponen (kembali 1.13.1 / 2.19.6 / image slim) | Isi katalog OM bila DB sudah di-drop (reproducible, bukan mustahil) |
| Konfigurasi (`deploy/`, `docs/`) via tag git | Riwayat DQ (test case + hasil) — dibangun ulang oleh DAG |
| Lineage dbt | Dashboard/artefak yang hanya ada di OM |
Alasan ini dapat diterima: seluruh isi katalog berasal dari
`scripts/ingest-openmetadata.sh` + DAG `sicabe_batch_daily`, jadi bisa dibangun ulang.
## 6. Titik tidak-balik (penting)
| Setelah subtask | Kondisi |
|---|---|
| 05 (+07) | Airflow memakai image ber-plugin; rollback = kembalikan 4 baris `AIRFLOW_IMAGE` |
| 10 | OpenSearch 3.x; index lama sudah hilang saat container dibuat ulang |
| **12** | **`openmetadata_db` di-drop → satu-satunya titik yang kehilangan data** |
| 13-15 | OM 2.0.2 jalan dgn password admin dari `.env` |
+106
View File
@@ -0,0 +1,106 @@
# Hasil R18-6 — Uji End-to-End: OM membangkitkan DAG ingestion → Airflow 3.3.2
> **Tanggal**: 2026-10-01/02 · **Lingkungan**: PRODUKSI (Airflow 3.3.2 + OM 2.0.3)
> **Tujuan**: membuktikan jalur "OpenMetadata mengirim DAG ke Airflow" secara **utuh** —
> bukan hanya tingkat impor (itu sudah diukur di H7) — dan sekaligus menutup pertanyaan H7
> secara definitif.
> ⚠️ Uji ini **membuat** pipeline sementara di OM produksi lalu **menghapusnya kembali**.
---
## 1. VERDICT: 🟢 **BERHASIL PENUH — H7 tertutup secara definitif**
| Tahap | Hasil |
|---|---|
| OM membuat ingestion pipeline (`metadata`) untuk `trino_sicabe` | ✅ dibuat |
| OM men-deploy DAG ke Airflow (lewat plugin `/pluginsv2/`) | ✅ **HTTP 200** |
| DAG muncul di Airflow 3.3.2 | ✅ `r18_e2e_ingestion.py` |
| **Error impor** | ✅ **0** (`No data found`) |
| Trigger dari OM menjalankan DAG | ✅ HTTP 200 (percobaan ke-2) |
| **`dag_run`** | ✅ **`success`** (17 detik) |
| **`task_instance` (`ingestion_task`)** | ✅ **`success`** |
**Ringkasan dari log task (bukti terkuat):**
```
Processed records: 4 · Updated records: 0 · Errors: 0 · Success %: 100.0
Processed records: 5 · Updated records: 0 · Errors: 0 · Success %: 100.0
Workflow Success %: 100.0
Workflow finished in time: 6s 668.015ms
Done.
```
➡️ **Kesimpulan**: paket yang hilang akibat melepas extra `[airflow]`
(`tornado`, `elasticsearch`, `opensearchpy`, `providers-elasticsearch`,
`providers-opensearch`) **tidak mengganggu jalur ingestion metadata**. H7 kini bukan lagi
"terukur di tingkat impor", melainkan **terbukti sampai eksekusi**.
---
## 2. TEMUAN BARU — plugin memvalidasi LEBIH KETAT daripada server OM
Ini temuan integrasi yang belum tercatat sebelumnya, dan menjelaskan kegagalan deploy yang
sempat terjadi tiga kali:
```
POST /v1/services/ingestionPipelines/deploy/<id> → 400
{"error":"Extra parameter 'serviceName'"}
{"error":"Extra parameter 'markDeletedTablesFromFilterOnly'"}
{"error":"Extra parameter 'serviceConnections'"}
```
**Artinya**: pipeline yang **diterima** server OM saat dibuat (`POST /v1/services/ingestionPipelines`
→ 201) bisa **ditolak saat deploy** oleh plugin di sisi Airflow. Validasi plugin lebih ketat
daripada skema server.
**Yang bekerja** — `sourceConfig.config` **paling minimal**:
```json
{ "airflowConfig": { "scheduleInterval": "0 0 * * *", "retries": 0, "startDate": <epoch-ms> },
"name": "<nama>",
"pipelineType": "metadata",
"service": { "id": "<id service>", "type": "databaseService" },
"sourceConfig": { "config": { "type": "DatabaseMetadata" } } }
```
- **Jangan** menambahkan `serviceName`, `serviceConnections`, `includeTables`,
`markDeletedTablesFromFilterOnly`, dsb. pada `DatabaseMetadata` — ditolak sebagai
*extra parameter*.
- Koneksi diambil dari **service record** yang sudah ada (dibuat `bootstrap.sh`) — dan
**bekerja** ✅. (Catatan: ini berbeda dari jalur SDK yang punya masalah koneksi tersimpan
kehilangan secret → `401`; pada jalur OM-orchestrated koneksi tersimpan justru dipakai
dengan benar.)
- Untuk pipeline **TestSuite**, `serviceConnections` justru **diterima** (seeder DQ
memakainya) — jadi aturan "extra parameter" itu **per tipe pipeline**, bukan global.
---
## 3. Perilaku lain yang terkonfirmasi
| Perilaku | Bukti |
|---|---|
| **Trigger gagal di percobaan pertama**, berhasil di percobaan kedua | DAG baru dibuat → `dag-processor` belum selesai mem-parsing. Perlu jeda ±20 detik (seeder DQ sudah mengantisipasi ini) |
| `airflow dags list` membaca **metadata DB**, bukan folder | Sempat menyesatkan saat uji folder mount |
| CLI Airflow 3: `airflow dags list-runs` **bukan** bentuk yang valid | Status run paling andal dibaca dari tabel `dag_run`/`task_instance` di metadata DB |
| Menghapus pipeline (`hardDelete`) menghapus **berkas DAG** dari volume | File `r18_e2e_ingestion.py` hilang; catatan DAG di DB menjadi *stale* pada siklus parse berikutnya |
---
## 4. Kebersihan setelah uji
| Item | Status |
|---|---|
| Pipeline `r18_e2e_ingestion` di OM | ✅ **dihapus** (HTTP 200, `hardDelete`) |
| Berkas DAG di volume `airflow-dags` | ✅ **hilang** (kembali 4 berkas seperti semula) |
| Catatan DAG di metadata DB Airflow | ⏳ menjadi *stale* otomatis pada siklus parse berikutnya (berkasnya sudah tidak ada) |
| DAG produksi lain | ✅ tidak tersentuh |
---
## 5. Kesalahan saya selama R18-6 (agar tidak terulang)
| # | Kesalahan | Akibat |
|---|---|---|
| 1 | Menyusun `sourceConfig.config` dengan field lengkap ala UI | Deploy ditolak 3× (`Extra parameter …`) — seharusnya mulai dari yang **minimal** |
| 2 | Menganggap semua tipe pipeline menerima field yang sama | `serviceConnections` diterima di TestSuite, **ditolak** di DatabaseMetadata |
| 3 | Memakai `airflow dags list-runs` | Bentuk CLI berbeda di Airflow 3 → pakai tabel DB |