Mengapa Static Analysis PL/SQL Harus Ada di Pipeline CI
Kode basis data seperti package PL/SQL, trigger, dan migration script kerap diperlakukan berbeda dari kode backend application. Verifikasi sintaks sering kali baru terjadi saat deployment runtime ke staging database. Praktik ini lambat dan berisiko meloloskan anti-pattern kritis ke production.
Oracle SQLcl menyediakan utilitas CodeScan bawaan yang menjalankan static code analysis langsung pada file sumber SQL dan PL/SQL tanpa memerlukan koneksi database aktif. Engine ini mengevaluasi Abstract Syntax Tree (AST) kode menggunakan aturan berbasis Arbori (turunan aturan Trivadis), memungkinkan tim mendeteksi bug fungsional, celah keamanan, dan inefisiensi performa sebelum kode masuk ke proses merge.
Arsitektur CI untuk Verifikasi Kode PL/SQL
Arsitektur pipeline beroperasi dengan model pre-merge validation pada Pull Request:
- Filter Perubahan (Delta Detection): Runner mengecek file dengan ekstensi
.sql,.pks, atau.pkbyang berubah terhadap target branch. - Headless Execution: Menjalankan SQLcl dalam mode silent (
/nolog) di dalam container ephemeral. - Scan Execution: CodeScan memindai file target menggunakan aturan Trivadis/Arbori yang telah disepakati.
- Report Parsing & Severity Threshold: Runner mem-parsing laporan output (JSON/XML) dan menghitung jumlah violation berdasarkan level keparahan (Severe, Warning, Info).
- Status Check: Pipeline mengembalikan
exit code 1jika ditemukan pelanggaran pada level Severe/High, memblokir pull request secara otomatis.
Menyiapkan SQLcl Headless di Container GitHub Actions
SQLcl membutuhkan runtime Java (JDK 11 atau 17). Eksekusi paling efisien di CI adalah menggunakan container Oracle Linux resmi atau image Java standar dengan binary SQLcl yang di-cache.
Perintah minimal untuk menjalankan pemindaian headless tanpa kredensial database adalah:
sql -s /nolog <<EOF
codescan -input ./src/database -output ./reports/codescan-report.json -format json
exit
EOFFlag -s mengaktifkan silent mode untuk meredam banner interaktif SQLcl, sedangkan /nolog mencegah SQLcl meminta autentikasi database saat inisialisasi.
Kustomisasi Aturan Arbori: Menangkap Anti-Pattern Kritis
CodeScan mengevaluasi ekspresi Arbori terhadap parse tree code. Berikut tiga anti-pattern umum yang wajib diblokir di pipeline CI beserta implementasi target deteksinya.
1. Swallowed Exception (WHEN OTHERS Tanpa RAISE)
Menangkap exception dengan WHEN OTHERS tanpa melakukan re-raise (RAISE atau RAISE_APPLICATION_ERROR) menyembunyikan fatal error di runtime dan merusak integritas transaksi data.
-- Anti-pattern:
EXCEPTION
WHEN OTHERS THEN
NULL; -- Error ditelan tanpa trace
END;
-- Target Arbori check:
whenOthersWithoutRaise:
[node) exception_handler
& [node) includes 'WHEN'
& [node) includes 'OTHERS'
& ! [node) includes 'RAISE'
& ! [node) includes 'RAISE_APPLICATION_ERROR';2. Penggunaan SELECT *
Klausa SELECT * di dalam package PL/SQL rentan terhadap error kompilasi ketika ada modifikasi kolom tabel dan menyebabkan overhead network buffer yang tidak terpakai.
-- Anti-pattern:
SELECT * INTO l_record FROM employees WHERE department_id = 10;
-- Arbori query pattern:
selectStarCheck:
[query) query_block
& [query) includes '*'
& ! [query) includes 'COUNT(*)';3. Hardcoded Literals
String SQL dinamis dengan literal hardcode memicu SQL injection dan memenuhi SGA shared pool karena ketiadaan bind variables.
Workflow CI Minimal (GitHub Actions)
Workflow berikut mendemonstrasikan eksekusi scan pada GitHub Actions runner, mengekspor hasil ke JSON, dan mengevaluasi severity menggunakan jq.
name: PL/SQL Static Analysis
on:
pull_request:
paths:
- 'database/**.sql'
- 'database/**.pks'
- 'database/**.pkb'
jobs:
sqlcl-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Java JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache SQLcl
id: cache-sqlcl
uses: actions/cache@v4
with:
path: ~/sqlcl
key: sqlcl-latest
- name: Install SQLcl
if: steps.cache-sqlcl.outputs.cache-hit != 'true'
run: |
curl -s -o sqlcl.zip https://download.oracle.com/otn_software/java/sqldev/sqlcl-latest.zip
unzip -q sqlcl.zip -d ~/sqlcl
chmod +x ~/sqlcl/sqlcl/bin/sql
- name: Run CodeScan
run: |
export PATH="$HOME/sqlcl/sqlcl/bin:$PATH"
mkdir -p reports
sql -s /nolog <<EOF
codescan -input database/ -output reports/scan-results.json -format json
exit
EOF
- name: Validate Severity Threshold
run: |
if [ ! -f reports/scan-results.json ]; then
echo "Report file not generated!"
exit 1
fi
# Hitung issue dengan severity 1 (Severe) atau 2 (High)
CRITICAL_ISSUES=$(jq '[.issues[] | select(.severity == "1" or .severity == "Severe")] | length' reports/scan-results.json)
WARNING_ISSUES=$(jq '[.issues[] | select(.severity == "2" or .severity == "Warning")] | length' reports/scan-results.json)
echo "Scan Summary: $CRITICAL_ISSUES critical issues, $WARNING_ISSUES warnings."
if [ "$CRITICAL_ISSUES" -gt 0 ]; then
echo "ERROR: Ditemukan $CRITICAL_ISSUES pelanggaran kritis pada PL/SQL."
jq '.issues[] | select(.severity == "1" or .severity == "Severe") | {rule: .ruleId, file: .fileName, line: .line, desc: .description}' reports/scan-results.json
exit 1
fiTrade-offs dan Limitasi
- Dynamic SQL: CodeScan membedah token sintaks statis. Dynamic SQL di dalam
EXECUTE IMMEDIATEyang dirakit secara modular tidak dapat dianalisis semantik isinya secara menyeluruh. - Kebutuhan Resource: Pemindaian direktori monorepo database besar membutuhkan alokasi memori heap JVM yang cukup. Jika runner OOM (Out Of Memory), batasi scan hanya pada file yang diubah menggunakan parameter
git diff --name-only. - Database Dependency: CodeScan mengecek kaidah sintaks dan konvensi penulisan. Alat ini tidak memverifikasi validitas nama tabel atau relasi skema terhadap database riil.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!