Menjalankan pipeline CI/CD pada runner Windows sering kali menimbulkan kegagalan build yang tidak terjadi di Linux atau macOS. Sebagian besar masalah ini bukan berasal dari kode aplikasi, melainkan perbedaan arsitektur sistem operasi. Tiga masalah paling umum yang sering menghentikan eksekusi workflow Windows adalah pembatasan MAX_PATH pada Win32 API, inkonsistensi line ending (CRLF vs LF), serta penguncian file (file locking) eksklusif yang memicu error EPERM atau EBUSY.
1. Mengatasi Batasan MAX_PATH (260 Karakter)
Windows API secara default memberlakukan batas panjang path sebesar 260 karakter (didefinisikan sebagai konstanta MAX_PATH). Struktur proyek modern dengan direktori bertingkat—seperti node_modules, cache Cargo, atau intermediate output C++—mudah melampaui limit ini dan memunculkan error seperti Filename too long atau PathTooLongException.
Aktivasi Long Paths di Level Sistem dan Git
Untuk mengaktifkan dukungan jalur panjang, Windows Registry dan Git perlu dikonfigurasi secara eksplisit di awal job runner:
# Aktifkan LongPaths di Registry Windows via PowerShell
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1
# Aktifkan pembacaan long path pada Git client
git config --system core.longpaths trueSolusi Compiler dan Tooling
Meskipun registry telah aktif, beberapa compiler atau runtime lawas tetap membaca path berbasis Win32 non-Unicode API. Gunakan pendekatan berikut jika terjadi kegagalan build compiler:
- MSVC (cl.exe): Gunakan prefix
\\?\untuk path absolut pada script generator, atau pastikan executable compiler memiliki manifest XML yang menyertakan tag<longPathAware>true</longPathAware>. - Clang/LLVM: Clang mendukung path panjang secara native pada versi modern, tetapi argumen include path yang diteruskan via shell Windows (PowerShell/CMD) dapat terpotong jika total buffer command line melebihi 32.767 karakter. Solusinya, gunakan response files (contoh:
clang++ @args.rsp). - Mount Virtual Drive (Subst): Jika executable pihak ketiga menolak path panjang, pendekkan direktori kerja runner menggunakan virtual drive mapping:
subst X: D:\a\my-repo\nested\very\deep\directory
cd X:\
# Jalankan perintah build di root drive X:
subst X: /D2. Standardisasi Line Ending: CRLF vs LF
Secara default, Git for Windows sering mengubah LF menjadi CRLF saat checkout (jika core.autocrlf aktif). Perubahan ini dapat merusak verifikasi hash file (checksum verification), eksekusi bash script (/bin/sh^M: bad interpreter), serta parser compiler yang sensitif terhadap byte carriage return.
Solusi Tepat: Konfigurasi .gitattributes
Hindari mengandalkan konfigurasi lokal mesin individual. Tambahkan file .gitattributes di root repositori untuk memaksa LF secara seragam di seluruh runner:
# Force LF untuk semua file teks
* text=auto eol=lf
# Ekstensi spesifik yang wajib LF murni
*.sh text eol=lf
*.bash text eol=lf
*.py text eol=lf
# File biner tidak boleh dimodifikasi
*.png binary
*.jar binary
*.exe binaryPada pipeline CI, matikan konversi otomatis Git sebelum tahap checkout dilakukan:
git config --global core.autocrlf false3. Mengatasi File Locking (EPERM dan EBUSY)
Berbeda dengan kernel Linux yang mengizinkan penghapusan file yang sedang terbuka oleh proses lain (unlink on unclosed file descriptors), Windows kernel menerapkan mandatory file locking. Jika file sedang dibaca oleh Windows Defender, proses telemetry, build daemon (seperti Gradle atau MSBuild), upaya penimpaan atau pembersihan folder build/ atau dist/ akan gagal dengan status EPERM: operation not permitted.
Menonaktifkan Defender / Realtime Antivirus
Pada pipeline CI publik, runner dibuat sementara (ephemeral), sehingga scanning antivirus realtime sering kali hanya memperlambat proses dan mengunci file binary output. Nonaktifkan scanning pada direktori workspace runner:
# PowerShell: Exclude folder workspace dari scanning Defender
Add-MpPreference -ExclusionPath $env:GITHUB_WORKSPACEMendeteksi dan Membunuh Proses yang Mengunci File
Jika proses background memblokir penghapusan direktori, gunakan utility handle.exe dari Sysinternals untuk melacak proses tersebut, atau gunakan PowerShell untuk menghentikan daemon yang tersisa:
# Mencari process ID yang memegang handle ke direktori tertentu via Sysinternals handle64
handle64.exe -nobanner $env:GITHUB_WORKSPACE\target\debug
# Menghentikan paksa daemon MSBuild atau Node yang tertinggal
Get-Process -Name "msbuild", "node", "vctip" -ErrorAction SilentlyContinue | Stop-Process -Force4. Contoh Workflow GitHub Actions yang Robust
Workflow berikut menggabungkan penanganan batasan path, standardisasi checkout tanpa konversi CRLF, eliminasi intervensi Defender, serta penanganan cleanup yang aman pada runner windows-latest.
name: Windows Robust CI
on:
push:
branches: [main]
pull_request:
jobs:
build-windows:
runs-on: windows-latest
defaults:
run:
shell: pwsh
steps:
- name: Configure System-Level Prerequisites
run: |
# 1. Enable Long Paths
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1
git config --system core.longpaths true
# 2. Disable CRLF translation
git config --global core.autocrlf false
# 3. Add workspace to Defender exclusion list to prevent file locking
Add-MpPreference -ExclusionPath $env:GITHUB_WORKSPACE -ErrorAction SilentlyContinue
- name: Checkout Code
uses: actions/checkout@v4
with:
# Memastikan file diambil sesuai line-ending di tree repositori
set-safe-directory: true
- name: Build Application
run: |
# Contoh simulasi build
Write-Host "Compiling artifacts in: $env:GITHUB_WORKSPACE"
# Pasang flag compiler jika menggunakan build C++
$env:CFLAGS = "/utf-8"
$env:CXXFLAGS = "/utf-8"
# Simpan dummy build file di path dalam
$deepPath = New-Item -ItemType Directory -Path "target\build\intermediate\cache\x64" -Force
New-Item -ItemType File -Path "$deepPath\output.bin" -Value "artifact data" -Force
- name: Post-Build Cleanup / Unlock Verification
if: always()
run: |
# Hentikan background daemon yang mungkin memegang file lock
Get-Process -Name "msbuild", "link", "node" -ErrorAction SilentlyContinue | Stop-Process -Force
# Cleanup aman
if (Test-Path "target") {
Remove-Item -Path "target" -Recurse -Force -ErrorAction SilentlyContinue
}Ringkasan Tindakan Preventif
Kegagalan build di Windows hampir selalu dapat diprediksi dengan standarisasi lingkungan berikut:
- Gunakan
.gitattributesuntuk menegakkan LF dan matikancore.autocrlf. - Setel
LongPathsEnableddancore.longpaths truesebagai langkah pertama pipeline. - Kecualikan workspace build dari pemindaian antivirus dan pastikan background daemon dihentikan sebelum fase cleanup.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!