Lompat ke konten
dokumentasi.id
Commit bd74801
v2
Star10 rb

12

Build, Test, dan Rilis

Rilis ua-parser-js berjalan lewat tiga script di script/ dan tiga workflow di .github/workflows/. Semua perintah masuk lewat npm run, sehingga CI tidak perlu menulis ulang langkahnya. package.json:244-256

ScriptPerintah
build./script/build-esm.js && ./script/build-dist.sh
build+testnpm run build && npm run test
test./script/test-all.sh
test:jshintjshint src/main
test:eslinteslint --no-config-lookup src
test:mochamocha --recursive test/unit
test:playwrightplaywright test test/e2e --browser all
test:lockfile-lintlockfile-lint -p package-lock.json
test:dts-linttsd --typings src/main/ua-parser.d.ts --files test/static/dts-lint.ts
test:fuzzjazzer ./test/fuzz/redos.js --sync
test:nycnyc --timeout=50000 --include=src/**/*.js npm run test

Build: build-esm.js lalu build-dist.sh

npm run build merangkai dua tahap dengan &&. Tahap pertama menghasilkan versi ESM dan deklarasi tipe. Tahap kedua memampatkan hasilnya menjadi berkas di dist/.

graph LR
  SRC["src/main/ua-parser.js<br/>+ 5 modul src lain"] --> ESM["script/build-esm.js"]
  ESM --> MJS["*.mjs hasil generate<br/>+ ua-parser-enums.d.ts"]
  MJS --> DIST["script/build-dist.sh"]
  SRC --> DIST
  DIST --> ART["dist/ua-parser.min.js<br/>dist/ua-parser.pack.js<br/>dist/ua-parser.min.mjs<br/>dist/ua-parser.pack.mjs"]
  style ESM fill:#f59e0b,color:#000
  style DIST fill:#f59e0b,color:#000
  style MJS fill:#8b5cf6,color:#fff
  style ART fill:#2d7d46,color:#fff
%% fig: Aliran dua tahap npm run build
%% desc: build-esm.js menghasilkan berkas .mjs dan .d.ts, lalu build-dist.sh memampatkan src dan .mjs menjadi empat berkas dist.
Fig. 1: Aliran dua tahap npm run buildbuild-esm.js menghasilkan berkas .mjs dan .d.ts, lalu build-dist.sh memampatkan src dan .mjs menjadi empat berkas dist.

build-esm.js memakai satu fungsi generateFile untuk setiap entri: berkas src dibaca, daftar replacements dijalankan, lalu hasilnya ditulis ke dest dengan header // DO NOT EDIT THIS FILE! dan komentar // Source: /${src}. script/build-esm.js:14-30

Daftar files berisi delapan entri. Enam di antaranya menghasilkan pasangan .js ke .mjs untuk modul utama, bot-detection, browser-detection, device-detection, extensions, dan helpers. Dua entri membaca src/enums/ua-parser-enums.js. script/build-esm.js:32-91

Berkas sumberBerkas hasil
src/main/ua-parser.jssrc/main/ua-parser.mjs
src/bot-detection/bot-detection.jssrc/bot-detection/bot-detection.mjs
src/browser-detection/browser-detection.jssrc/browser-detection/browser-detection.mjs
src/device-detection/device-detection.jssrc/device-detection/device-detection.mjs
src/enums/ua-parser-enums.jssrc/enums/ua-parser-enums.mjs
src/enums/ua-parser-enums.jssrc/enums/ua-parser-enums.d.ts
src/extensions/ua-parser-extensions.jssrc/extensions/ua-parser-extensions.mjs
src/helpers/ua-parser-helpers.jssrc/helpers/ua-parser-helpers.mjs

Entri enums dipakai dua kali, sekali untuk .mjs dan sekali untuk .d.ts. Penggantian untuk berkas deklarasi mengubah object.freeze menjadi Readonly<, menambah typeof, mengganti }); menjadi }>;, lalu membuang baris module.exports. script/build-esm.js:68-78

Seluruh entri diproses berurutan pada satu baris terakhir: files.forEach(module => generateFile(module)). script/build-esm.js:93

build-dist.sh menetapkan empat pasangan path: src/main/ua-parser.js ke dist/ua-parser.min.js dan dist/ua-parser.pack.js, serta src/main/ua-parser.mjs ke dist/ua-parser.min.mjs dan dist/ua-parser.pack.mjs. script/build-dist.sh:3-9

Empat panggilan uglifyjs mengisi keempat berkas itu. Varian min hanya mempertahankan komentar yang cocok dengan /^ UA/. Varian pack menambahkan --compress --mangle, dan berkas .mjs memakai flag tambahan --module. script/build-dist.sh:11-23

⚠️ Tahap kedua membaca src/main/ua-parser.mjs, yaitu berkas hasil tahap pertama. Karena itu kedua script dirangkai dengan && di script build. Jika build-dist.sh dijalankan sendiri setelah perubahan pada src/main/ua-parser.js, yang dipampatkan adalah versi .mjs yang usang. package.json:244-256

Perkakas kedua tahap adalah devDependencies: uglify-js untuk uglifyjs, ditambah jshint, eslint, mocha, @playwright/test, lockfile-lint, tsd, nyc, dan @jazzer.js/core untuk test. package.json:262-276

Rantai test-all.sh

npm run test hanya memanggil script/test-all.sh. Script itu menjalankan npm run build lebih dulu, lalu enam langkah lain. Setiap langkah diakhiri || exit 1, sehingga kegagalan pertama menghentikan rangkaian. script/test-all.sh:3-6

graph LR
  B["npm run build"] --> J["test:jshint"]
  J --> E["test:eslint"]
  E --> M["test:mocha"]
  M --> P["test:playwright"]
  P --> L["test:lockfile-lint"]
  L --> D["test:dts-lint"]
  B -. "exit 1" .-> FAIL["rangkaian berhenti"]
  style B fill:#f59e0b,color:#000
  style D fill:#2d7d46,color:#fff
  style FAIL fill:#dc2626,color:#fff
%% fig: Urutan gerbang di script test-all.sh
%% desc: build jalan lebih dulu, lalu tujuh langkah lint dan test berurutan; kegagalan satu langkah menghentikan seluruh rangkaian.
Fig. 2: Urutan gerbang di script test-all.shbuild jalan lebih dulu, lalu tujuh langkah lint dan test berurutan; kegagalan satu langkah menghentikan seluruh rangkaian.
UrutanLangkahPerintahCakupan
1buildnpm run buildsrc/ lalu dist/
2lint jsnpm run test:jshintsrc/main
3lint jsnpm run test:eslintsrc
4unit testnpm run test:mochatest/unit rekursif
5e2enpm run test:playwrighttest/e2e, semua browser
6lint lockfilenpm run test:lockfile-lintpackage-lock.json
7lint tipenpm run test:dts-lintsrc/main/ua-parser.d.ts dan test/static/dts-lint.ts

Tiga langkah pertama mencakup build, jshint untuk src/main, dan eslint untuk seluruh src. Langkah keempat menjalankan unit test lewat mocha. script/test-all.sh:8-17

Tiga langkah terakhir menjalankan playwright test test/e2e --browser all, lockfile-lint -p package-lock.json, dan tsd terhadap deklarasi tipe utama. script/test-all.sh:19-32

test-all.sh tidak memanggil test:fuzz maupun test:nyc. Keduanya harus dijalankan manual bila dibutuhkan untuk uji ReDoS atau pengukuran coverage. package.json:244-256

CI: Build & Test

Workflow CI: Build & Test berjalan pada setiap push dan pull_request dengan permission contents: read. Job run-test memakai ubuntu-latest dan timeout-minutes: 30. .github/workflows/ci-build-test.yml:9-19

DimensiNilai
archamd64
node-versionlts/iron, lts/jod, lts/krypton
includearch: ppc64le dengan node-version: 20
runnerubuntu-latest
batas waktu job30 menit

Sebelum test, workflow mengaktifkan Corepack, memasang dependency dengan npm ci, lalu memasang browser Playwright dengan npx playwright install --with-deps. Langkah terakhir menjalankan npm run build+test, jadi build dan seluruh rangkaian test ikut berjalan di CI. Masing-masing dari tiga langkah itu diberi timeout-minutes: 10. .github/workflows/ci-build-test.yml:33-44

gantt
    dateFormat mm:ss
    axisFormat %M:%S
    section run-test job, batas 30m
    Install dependencies, npm ci :d1, 00:00, 10m
    Install Playwright browsers :d2, after d1, 10m
    Run the test suite, npm run build+test :d3, after d2, 10m
%% fig: Anggaran waktu job CI Build & Test
%% desc: Tiga step utama job run-test masing-masing dibatasi 10 menit, sementara seluruh job dibatasi 30 menit.
Fig. 3: Anggaran waktu job CI Build & TestTiga step utama job run-test masing-masing dibatasi 10 menit, sementara seluruh job dibatasi 30 menit.

Publikasi: npm dan Docker

Kedua workflow publikasi dipicu oleh event release bertipe published, bukan oleh push. publish-npm.yml meminta contents: read dan id-token: write. .github/workflows/publish-npm.yml:3-13

sequenceDiagram
  participant GH as release published
  participant NPM as publish-npm.yml
  participant DKR as publish-docker.yml
  participant REG as registry npmjs dan Docker Hub
  GH->>NPM: memicu job Publish: NPM
  GH->>DKR: memicu job Publish: Docker
  NPM->>NPM: corepack enable npm, npm ci
  NPM->>REG: npm publish --provenance --access public
  DKR->>DKR: ambil VERSION dari GITHUB_REF
  DKR->>DKR: version_check dengan pola versi mayor minimal 2
  alt versi mayor 2 ke atas
    DKR->>REG: build-push linux/amd64 dan linux/arm64, tag VERSION dan latest
  else versi mayor 1.x
    DKR-->>DKR: step buildx, login, dan push dilewati
  end
%% fig: Dua jalur publikasi dari satu release
%% desc: Satu event release memicu publish npm dan publish Docker; Docker hanya jalan untuk versi mayor 2 ke atas.
Fig. 4: Dua jalur publikasi dari satu releaseSatu event release memicu publish npm dan publish Docker; Docker hanya jalan untuk versi mayor 2 ke atas.

publish-npm.yml menjalankan npm publish --provenance --access public dengan NODE_AUTH_TOKEN dari secrets.NPM_TOKEN, memakai Node 22 dan registry-url: 'https://registry.npmjs.org'. Flag --provenance itulah alasan permission id-token: write dibutuhkan. .github/workflows/publish-npm.yml:28-31

publish-docker.yml mengambil versi dari GITHUB_REF lewat Extract version from release tag, lalu menguji $VERSION =~ ^([2-9]|[0-9]{2,})\.. Step Buildx, login, dan push hanya berjalan bila steps.version_check.outputs.docker_support == 'true'. .github/workflows/publish-docker.yml:19-32

Push menghasilkan dua tag, faisalman/ua-parser-js:VERSION dan faisalman/ua-parser-js:latest, untuk linux/amd64 dan linux/arm64. Cache dipakai lewat registry faisalman/ua-parser-js:buildcache dengan mode=max. .github/workflows/publish-docker.yml:45-57

Image dibangun multi-stage dari node:lts-alpine. Dependency dipasang dengan npm install --omit=dev, lalu src/, script/cli.js, dan node_modules disalin ke stage runtime. ENTRYPOINT menjalankan node ./script/cli.js, sehingga perintah di dalam image adalah CLI ua-parser-js; image tidak memuat dist/ karena cli.js membaca src/main/ua-parser. Dockerfile:1-14

⚠️ Rilis 1.x tidak menghasilkan image Docker. version_check hanya bernilai true untuk versi mayor 2 ke atas, dan pada versi lain step push dilewati tanpa error, jadi job tetap hijau meski tidak ada image yang diunggah. .github/workflows/publish-docker.yml:19-32

Paket npm yang terbit hanya memuat dist/*.?(m)js, dist/icons, dan src, dengan bin menunjuk ./script/cli.js. Artinya dist/ harus sudah ada sebelum npm publish, dan urutan itu dijamin oleh langkah build di workflow test. package.json:237-243