Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Postman + GitLab CI / Jenkins

Mở đầu — vì sao bài này quan trọng

Ở bài trước, bạn đã học cách đưa Postman vào GitHub Actions — nơi mọi thứ khá "thân thiện" với người mới: file YAML gọn gàng, marketplace đầy actions dựng sẵn, log đẹp mắt. Nhưng khi bước chân vào các công ty Việt Nam có quy mô lớn hơn, bạn sẽ nhanh chóng nhận ra một sự thật: rất nhiều đội ngũ không dùng GitHub Actions. Họ dùng GitLab CI (đặc biệt phổ biến ở các ngân hàng, fintech, công ty outsourcing vì GitLab có bản self-hosted — dữ liệu không rời khỏi máy chủ nội bộ) hoặc Jenkins (một "lão làng" vẫn thống trị ở các doanh nghiệp lớn, viễn thông, và những hệ thống legacy đã chạy hàng chục năm).

Nếu bạn là một QA engineer chỉ biết chạy Newman trên GitHub Actions, bạn sẽ "đứng hình" khi vào ngày đầu tiên đi làm và sếp nói: "Em tích hợp bộ API test này vào pipeline GitLab của team đi". Đây là bài học giúp bạn tự tin làm được điều đó trên hai nền tảng CI phổ biến nhất tại Việt Nam ngoài GitHub Actions. Chúng ta sẽ không lặp lại lý thuyết Newman (bài 13) hay tư duy CI/CD chung chung, mà đi thẳng vào cách viết cấu hình chuẩn cho GitLab CI và Jenkins, cách xử lý artifact, biến bí mật, và các "cạm bẫy" đặc thù của từng nền tảng.

Khái niệm cốt lõi

GitLab CI hoạt động thế nào

GitLab CI được điều khiển bởi một file duy nhất đặt ở gốc repository: .gitlab-ci.yml. GitLab đọc file này và tự động sinh ra pipeline. Ba khái niệm bạn phải nắm:

  • Stage (giai đoạn): nhóm các job chạy song song. Các stage chạy tuần tự theo thứ tự khai báo. Ví dụ build → test → deploy.
  • Job (công việc): đơn vị thực thi nhỏ nhất. Mỗi job chạy trong một container riêng (nhờ Docker executor).
  • Runner: máy thực thi job. Có thể là shared runner của GitLab.com hoặc runner riêng công ty tự cài (rất phổ biến ở VN vì lý do bảo mật).
Điểm mấu chốt với Postman: mỗi job chỉ định một image Docker. Postman phát hành sẵn image chính thức postman/newman (và biến thể postman/newman:alpine nhẹ hơn nhiều). Bên trong image này đã có sẵn Node.js và Newman — bạn không cần cài đặt gì thêm, chỉ việc gọi lệnh newman run.

Jenkins hoạt động thế nào

Jenkins là một máy chủ tự động hóa (automation server) mà công ty tự cài trên hạ tầng của họ. Khác với GitLab CI (cấu hình khai báo, chạy trong container), Jenkins linh hoạt hơn nhưng cũng "thủ công" hơn. Có hai phong cách:

  • Jenkinsfile (Pipeline as Code): viết pipeline bằng Groovy trong file Jenkinsfile đặt ở repo. Đây là cách hiện đại, được khuyến nghị.
  • Cấu hình qua giao diện web (Freestyle job): click chuột trên UI. Cách này cũ, khó version-control, nhưng nhiều team legacy vẫn dùng.
Với Jenkins, bạn có hai chiến lược chạy Newman: (1) dùng agent Docker postman/newman giống GitLab, hoặc (2) cài Node.js + Newman trực tiếp trên máy Jenkins agent rồi gọi lệnh. Chiến lược (1) sạch sẽ và tái lập được, luôn nên ưu tiên nếu Jenkins agent có Docker.

Điểm chung: xuất từ Postman trước

Dù CI là gì, quy trình đầu vào luôn giống nhau: bạn export Collection và Environment thành file JSON rồi commit vào repo (thường trong thư mục postman/). CI chỉ đơn giản là gọi newman run collection.json -e environment.json. Một số team dùng cách khác là truyền URL API của Postman Cloud, nhưng commit file JSON vào Git là cách dễ kiểm soát version và review nhất — mỗi thay đổi test đều hiện rõ trong pull request.

Tình huống thực tế

Ví dụ 1 — Fintech Hà Nội chuyển từ Jenkins thủ công sang GitLab CI

Một công ty fintech tại Hà Nội (khoảng 40 kỹ sư) có một QA tên Linh chịu trách nhiệm regression cho API ví điện tử. Trước đây, mỗi lần release, Linh phải mở Postman trên máy cá nhân, bấm Runner, chạy 180 request thủ công, mất 25 phút và đôi khi quên chạy. Đội DevOps đã có sẵn GitLab self-hosted.

Linh export collection thành wallet-api.postman_collection.json, environment staging thành staging.postman_environment.json, commit vào thư mục postman/, rồi thêm file .gitlab-ci.yml:

stages:
  - test

api-regression: stage: test image: postman/newman:alpine script: - newman run postman/wallet-api.postman_collection.json -e postman/staging.postman_environment.json --reporters cli,junit --reporter-junit-export newman-report.xml artifacts: when: always reports: junit: newman-report.xml paths: - newman-report.xml expire_in: 1 week

Bài học rút ra: chỉ với 15 dòng YAML, bộ test giờ chạy tự động trên mỗi merge request. Chi tiết quan trọng là when: always trong artifacts — nếu không có, khi test fail thì GitLab sẽ không lưu report, và bạn mất luôn bằng chứng để điều tra lỗi. Đây là lỗi mà rất nhiều người mới mắc phải. Sau khi triển khai, thời gian regression giảm từ 25 phút thủ công xuống còn 4 phút tự động, và tỷ lệ "quên chạy test" về 0.

Ví dụ 2 — Công ty outsourcing dùng Jenkins với Jenkinsfile

Một công ty gia công phần mềm ở TP.HCM làm dự án cho khách Nhật, bắt buộc dùng Jenkins vì khách hàng đã đầu tư hạ tầng Jenkins từ trước. Anh Đức, SDET của dự án, viết Jenkinsfile dùng Docker agent:

pipeline {
    agent none
    stages {
        stage('API Test') {
            agent {
                docker { image 'postman/newman:alpine' }
            }
            steps {
                sh '''
                    newman run postman/order-api.postman_collection.json \
                      -e postman/staging.postman_environment.json \
                      --reporters cli,junit \
                      --reporter-junit-export newman-report.xml
                '''
            }
            post {
                always {
                    junit 'newman-report.xml'
                    archiveArtifacts artifacts: 'newman-report.xml', allowEmptyArchive: true
                }
            }
        }
    }
}

Bài học rút ra: khối post { always { ... } } trong Jenkins tương đương when: always của GitLab — nó đảm bảo report được thu thập kể cả khi test fail (vì newman run sẽ trả về exit code khác 0 khi có assertion fail, làm stage bị đánh dấu FAILURE). Đặc biệt lệnh junit 'newman-report.xml' giúp Jenkins hiển thị kết quả test dưới dạng biểu đồ trực quan với số test pass/fail, thay vì phải đọc log thô. Điều khách Nhật đánh giá cao nhất là mỗi build đều có báo cáo JUnit rõ ràng, dễ audit.

Ví dụ 3 — Sự cố lộ token vì hard-code secret

Một startup thương mại điện tử ở Đà Nẵng suýt gặp sự cố bảo mật nghiêm trọng. Bạn QA mới hard-code luôn api_key và mật khẩu tài khoản test vào file staging.postman_environment.json rồi commit lên GitLab. May mắn là reviewer phát hiện trong merge request. Nếu lọt, bất kỳ ai truy cập repo đều thấy khóa API sandbox.

Cách khắc phục đúng: để trống các giá trị nhạy cảm trong file environment, và truyền chúng lúc chạy qua biến CI. Trên GitLab, vào Settings → CI/CD → Variables, thêm biến API_KEY (đánh dấu MaskedProtected). Trong .gitlab-ci.yml:

script:
  - newman run postman/order-api.postman_collection.json
      -e postman/staging.postman_environment.json
      --env-var "api_key=$API_KEY"
      --env-var "test_password=$TEST_PASSWORD"

Bài học rút ra: không bao giờ commit secret vào Git. Cả GitLab và Jenkins đều có kho biến bí mật riêng (Jenkins dùng Credentials + withCredentials). Cờ --env-var cho phép ghi đè biến của environment ngay lúc chạy, tách hoàn toàn "logic test" (trong Git) khỏi "bí mật" (trong CI). Đây là nguyên tắc vàng khi đưa Postman lên bất kỳ CI nào.

Hướng dẫn từng bước

Phần A — GitLab CI

  • Export từ Postman: chuột phải Collection → Export (chọn Collection v2.1). Với Environment: biểu tượng con mắt → Export. Lưu cả hai vào thư mục postman/ trong repo.
  • Làm sạch secret: mở file environment JSON, xóa các giá trị nhạy cảm (đặt "value": ""), giữ lại tên biến.
  • Tạo .gitlab-ci.yml ở gốc repo với nội dung tối thiểu:
stages:
  - test

api-test: stage: test image: postman/newman:alpine script: - newman run postman/collection.json -e postman/staging.postman_environment.json --env-var "api_key=$API_KEY" --reporters cli,junit --reporter-junit-export report.xml artifacts: when: always reports: junit: report.xml expire_in: 1 week

  • Thêm biến bí mật: Settings → CI/CD → Variables → Add variable, tạo API_KEY, tích Masked.
  • Commit và push. Vào tab Build → Pipelines để xem pipeline chạy. Vào một job để xem log, xem tab Tests để thấy kết quả JUnit.
  • (Tùy chọn) Chạy theo lịch: Build → Pipeline schedules để chạy regression mỗi đêm — hữu ích khi bạn muốn phát hiện API staging hỏng vào sáng hôm sau mà không phụ thuộc vào commit.

Phần B — Jenkins

  • Chuẩn bị: đảm bảo Jenkins agent có Docker (kiểm tra với admin). Cài plugin JUnitDocker Pipeline nếu chưa có.
  • Tạo Jenkinsfile ở gốc repo (dùng đoạn Groovy ở Ví dụ 2 làm mẫu). Nếu agent không có Docker, thay agent { docker {...} } bằng cài Newman thủ công:
stage('API Test') {
    agent any
    steps {
        sh 'npm install -g newman'
        sh 'newman run postman/collection.json -e postman/staging.postman_environment.json --reporters cli,junit --reporter-junit-export report.xml'
    }
    post { always { junit 'report.xml' } }
}
  • Thêm credential: Manage Jenkins → Credentials → Add, tạo Secret text với ID api-key. Dùng trong pipeline:
environment {
    API_KEY = credentials('api-key')
}

Rồi thêm --env-var "api_key=$API_KEY" vào lệnh newman.

  • Tạo Pipeline job: New Item → Pipeline, trỏ Pipeline script from SCM tới repo Git của bạn, branch chính, script path Jenkinsfile.
  • Build Now và xem kết quả. Sau build, khối Test Result Trend sẽ hiển thị biểu đồ pass/fail qua các build.

Lỗi thường gặp & mẹo

  • Đường dẫn file sai: lỗi phổ biến nhất là unable to read data from file. Nhớ rằng CI chạy từ gốc repo, nên đường dẫn phải là postman/collection.json chứ không phải chỉ collection.json. Kiểm tra bằng ls -R postman/ thêm vào script khi debug.
  • Quên when: always / post always: khi test fail, job fail, và mặc định report không được lưu — bạn mất bằng chứng lỗi. Luôn dùng when: always (GitLab) hoặc post { always {} } (Jenkins).
  • Pipeline "xanh" giả: nếu bạn viết newman run ... || true để pipeline luôn pass, bạn đã vô hiệu hóa toàn bộ giá trị của CI. Newman phải trả exit code khác 0 khi test fail để CI biết mà báo đỏ. Đừng nuốt lỗi.
  • Jenkins agent thiếu Docker: nếu docker báo permission denied hoặc not found, xác nhận với DevOps xem agent có Docker executor không. Nếu không, dùng phương án cài npm install -g newman trực tiếp — nhưng lưu ý agent cần có Node.js.
  • Timezone log lệch: runner GitLab/Jenkins thường chạy UTC, nên timestamp trong log lệch 7 tiếng so với giờ Việt Nam. Đừng hoảng khi thấy giờ "sai" — đó là UTC bình thường.
  • Mẹo — dùng --bail: khi muốn pipeline dừng ngay ở request đầu tiên fail (tiết kiệm thời gian cho smoke test), thêm cờ --bail. Với regression đầy đủ thì nên bỏ để chạy hết và thấy toàn cảnh.
  • Mẹo — tách môi trường bằng biến: dùng một biến CI ENV_FILE để chọn file environment (staging/production), giúp cùng một pipeline chạy được cho nhiều môi trường mà không sửa YAML.

Bài tập thực hành

  • Cơ bản (GitLab): tạo một repo GitLab (hoặc dùng repo có sẵn), export một collection nhỏ 5 request kèm environment, viết .gitlab-ci.yml để chạy chúng với reporter cli,junit. Xác nhận pipeline chạy và xem được tab Tests.
  • Bảo mật: cố tình đặt một biến api_key rỗng trong environment, thêm biến API_KEY Masked trong Settings CI/CD, và dùng --env-var để inject. Kiểm tra rằng giá trị bị che (masked) trong log.
  • Jenkins: nếu có quyền truy cập một Jenkins (hoặc cài Jenkins local qua Docker), viết Jenkinsfile chạy cùng collection đó bằng agent postman/newman:alpine, thu thập report bằng junit. So sánh trải nghiệm với GitLab.
  • Nâng cao: cấu hình một scheduled pipeline (GitLab) hoặc build periodically (Jenkins, cú pháp cron H 2 *) để chạy regression mỗi 2 giờ sáng. Ghi lại điều gì xảy ra khi API staging bị sập.
  • So sánh viết báo cáo: viết một đoạn ngắn (200 từ) so sánh trải nghiệm tích hợp Postman vào GitLab CI so với Jenkins — điểm nào dễ hơn, điểm nào khó hơn — dựa trên chính bài tập bạn vừa làm.

Tóm tắt

Bài này giúp bạn đưa bộ Postman/Newman vào hai nền tảng CI phổ biến tại Việt Nam ngoài GitHub Actions:

  • GitLab CI dùng file .gitlab-ci.yml khai báo, mỗi job chạy trong image Docker — chọn postman/newman:alpine là có sẵn Newman. Nhớ artifacts: when: always để giữ report khi fail.
  • Jenkins dùng Jenkinsfile (Groovy) với Docker agent hoặc cài Newman trực tiếp. Khối post { always { junit ... } } thu thập report; plugin JUnit hiển thị biểu đồ pass/fail.
  • Quy trình chung: export collection + environment thành JSON, commit vào postman/, làm sạch secret, gọi newman run với reporter JUnit, inject bí mật qua biến CI bằng --env-var.
  • Nguyên tắc vàng: không commit secret; đừng nuốt exit code của Newman; luôn thu report kể cả khi fail.
Nắm được cả GitLab CI lẫn Jenkins, bạn đã sẵn sàng làm việc ở hầu hết mọi công ty Việt Nam — dù họ dùng nền tảng nào. Bài tiếp theo, chúng ta sẽ nói về Postman Monitors để chạy collection theo lịch trực tiếp trên nền tảng Postman Cloud, một lựa chọn nhẹ nhàng khi bạn chưa muốn dựng cả pipeline CI.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi