OpenSearch: GitHub Actions 與 GitLab CI

直接從您的 GitHub Actions 或 GitLab CI pipeline 啟動一個真實的 OpenSearch 服務,執行測試,並自動銷毀服務

👋 歡迎來到 Stackhero 文件!

Stackhero 提供一個即用型的 OpenSearch 雲端 解決方案,帶來多項好處,包括:

  • 專屬私人 VM提供的最佳效能和強大的安全性
  • 支援 HTTPS 加密的可自訂域名
  • 整合的 OpenSearch Dashboards,實現流暢的數據可視化。

節省時間簡化您的生活:只需 5 分鐘即可嘗試 Stackhero 的 OpenSearch 雲端託管 解決方案!

本指南將帶您一步步在 CI pipeline 中運行一個真實、專屬的 OpenSearch 服務,可選擇 GitHub ActionsGitLab CI。依照這些步驟,您可以在接近正式環境的條件下,針對實際的 OpenSearch 實例測試您的程式碼,無需再依賴 mock 或模擬器。OpenSearch is an open source distributed search and analytics engine for fast full-text search and rich dashboards.

每次 pipeline 執行時,您都會獲得一個全新的 OpenSearch 實例。這代表您的測試將與正式環境中用戶所見的服務完全一致。此流程會自動建立一個臨時 stack,新增 OpenSearch,等待服務就緒,取得產生的認證資訊,利用 curl 執行 smoke test,最後在流程結束時自動清理所有資源。

您將會使用 Stackhero CLI,這是一個獨立的命令列工具,可讓您快速且簡單地啟動與管理 Stackhero 服務。

為了讓 CLI 能以非互動方式運作,您需要一組 access token(格式:usr-xxxxxx:tokenId)。這個 token 只需建立一次,然後將其加入您的 CI pipeline,作為安全加密的機密變數。

  1. 建立 token: 在您的 Stackhero 控制台,點擊右上角的大頭貼,進入 您的帳戶,選擇 Access tokens,然後點擊 Create token
  2. GitHub Actions: 在您的 repository,前往 Settings > Secrets and variables > Actions > New repository secret,將 token 輸入為 STACKHERO_TOKEN
  3. GitLab CI: 在您的專案,前往 Settings > CI/CD > Variables > Add variable,將 key 設為 STACKHERO_TOKEN,並勾選 Masked(如果您的 CI 僅在受保護分支執行,也可勾選 Protected)。

請勿將 access token 直接寫在 pipeline 的 YAML 檔案中。如果 token 出現在 YAML 內,任何有 repository 存取權的人都可能看到,甚至可能出現在建置日誌中。將其儲存為 CI 機密可確保加密與遮蔽,讓您的 token 保持安全。

以下是一個完整的腳本範例,涵蓋服務的全生命週期。您會發現設定非常簡單,只需幾個指令即可。您可以直接從下方各平台區段複製對應的 YAML 配置。

#!/bin/bash
set -euo pipefail

# STACKHERO_TOKEN 由 CI 機密提供,CLI 會自動讀取。

stackName="ci-opensearch-$$"          # 每次執行唯一的 stack 名稱
serviceStore="opensearch"             # OpenSearch 服務 store
instance="20G"        # 如有需要可調整(見步驟 3)
region="europe"                         # 區域名稱(可用 stackhero regions-list 查詢)

# 1. 在 runner 上安裝 CLI
curl -fsSL https://www.stackhero.io/install.sh | sh

# 2. 安裝 smoke test 所需的 client(jq + curl 為基本需求)
apt-get update && apt-get install -y --no-install-recommends jq curl

# 3. 為本次執行建立專屬 stack
stackId=$(stackhero --format=script stack-create --name="$stackName")
echo "Stack created: $stackId"

# 4. 新增 OpenSearch 並取得其 service id
serviceId=$(stackhero --format=script service-add \
  --stack="$stackId" \
  --service-store="$serviceStore" \
  --instance="$instance" \
  --region="$region")
echo "Service added: $serviceId"

# 5. 等待服務啟動(可能需數分鐘)
stackhero service-wait-for --service="$serviceId"

# 6. 讀取設定(包含產生的認證資訊)
config=$(stackhero service-configuration-get --service="$serviceId" --format=json)

# 7. 取得所需認證資訊
host=$(echo "$config" | jq -r '.configuration.domain')
user=$(echo "$config" | jq -r '.configuration.credentials.login')
password=$(echo "$config" | jq -r '.configuration.credentials.password')

# 8. Smoke test:Call the cluster health endpoint.
curl -fsS -u "$user:$password" "https://$host:9200/_cluster/health" | grep -q '"status"'

echo "✅ OpenSearch 已可從 CI 存取。"

資源清理(刪除服務、等待刪除完成、再刪除 stack)會在下方各平台專屬區段說明。這種做法可確保即使 smoke test 失敗也會進行完整清理。

Stack 必須為空才能刪除。請務必先刪除服務並等待其移除,再刪除 stack。service-wait-for 指令可確保服務已啟動或已刪除,是等待刪除的最佳工具。

下方範例預設使用 OpenSearch 的入門實例 20G。這對大多數工作負載來說已相當合適,您也可依需求調整。若要查詢 OpenSearch 所有可用實例類型,可執行:

# NAME 欄位即為 --instance 參數值
stackhero instances-store-list --service-store=opensearch

請將下列內容儲存為 .github/workflows/ci.yml。從此之後,每次 push 或 pull request 都會針對真實的 OpenSearch 實例執行測試。

name: 使用 OpenSearch  CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      STACKHERO_TOKEN: ${{ secrets.STACKHERO_TOKEN }}
      STACK_NAME: ci-opensearch-${{ github.run_id }}-${{ github.run_attempt }}
      INSTANCE: "20G"   # 如有需要可調整(見步驟 3)
      REGION: europe
    steps:
      - uses: actions/checkout@v4

      - name: 安裝 Stackhero CLI  client
        run: |
          curl -fsSL https://www.stackhero.io/install.sh | sh
          apt-get update && apt-get install -y --no-install-recommends jq curl

      - name: 建立 OpenSearch 服務
        run: |
          set -euo pipefail
          STACK_ID=$(stackhero --format=script stack-create --name="$STACK_NAME")
          echo "STACK_ID=$STACK_ID" >> "$GITHUB_ENV"
          SERVICE_ID=$(stackhero --format=script service-add \
            --stack="$STACK_ID" \
            --service-store="opensearch" \
            --instance="$INSTANCE" \
            --region="$REGION")
          echo "SERVICE_ID=$SERVICE_ID" >> "$GITHUB_ENV"
          stackhero service-wait-for --service="$SERVICE_ID"

      - name: 執行 OpenSearch 測試
        run: |
          set -euo pipefail
          config=$(stackhero service-configuration-get --service="$SERVICE_ID" --format=json)
          host=$(echo "$config" | jq -r '.configuration.domain')
user=$(echo "$config" | jq -r '.configuration.credentials.login')
password=$(echo "$config" | jq -r '.configuration.credentials.password')
          # Call the cluster health endpoint.
          curl -fsS -u "$user:$password" "https://$host:9200/_cluster/health" | grep -q '"status"'
          echo "✅ OpenSearch 已可從 CI 存取。"
          # 您也可以在此使用上述認證資訊執行自訂測試 ...

      - name: 清理資源(無論成功或失敗皆執行)
        if: always()
        run: |
          if [ -n "${SERVICE_ID:-}" ]; then
            stackhero service-delete --service="$SERVICE_ID" --confirm
            stackhero service-wait-for --service="$SERVICE_ID"
          fi
          if [ -n "${STACK_ID:-}" ]; then
            stackhero stack-delete --stack="$STACK_ID" --confirm
          fi

清理步驟設定為 if: always(),確保無論流程結果如何都會執行,讓您的 OpenSearch 實例被刪除,避免產生不必要的資源費用。

請將下列設定儲存為 .gitlab-ci.yml。每次 pipeline 執行時都會建立一個全新的 OpenSearch 實例供測試使用。

test:
  image: ubuntu:24.04
  variables:
    STACK_NAME: "ci-opensearch-$CI_PIPELINE_ID-$CI_JOB_ID"
    INSTANCE: "20G"   # 如有需要可調整(見步驟 3)
    REGION: "europe"
    SERVICE_STORE: "opensearch"
  # STACKHERO_TOKEN 來自您於步驟 1 建立的 CI/CD 變數。
  script:
    - set -euo pipefail
    - curl -fsSL https://www.stackhero.io/install.sh | sh
    - apt-get update && apt-get install -y --no-install-recommends jq curl
    - STACK_ID=$(stackhero --format=script stack-create --name="$STACK_NAME")
    - echo "STACK_ID=$STACK_ID" >> deploy.env
    - SERVICE_ID=$(stackhero --format=script service-add --stack="$STACK_ID" --service-store="$SERVICE_STORE" --instance="$INSTANCE" --region="$REGION")
    - echo "SERVICE_ID=$SERVICE_ID" >> deploy.env
    - stackhero service-wait-for --service="$SERVICE_ID"
    - config=$(stackhero service-configuration-get --service="$SERVICE_ID" --format=json)
    - host=$(echo "$config" | jq -r '.configuration.domain')
user=$(echo "$config" | jq -r '.configuration.credentials.login')
password=$(echo "$config" | jq -r '.configuration.credentials.password')
    # Call the cluster health endpoint.
    - curl -fsS -u "$user:$password" "https://$host:9200/_cluster/health" | grep -q '"status"'
    - echo "✅ OpenSearch 已可從 CI 存取。"
    # 您也可以在此使用上述認證資訊執行自訂測試 ...
  after_script:
    - test -f deploy.env && . ./deploy.env || true
    - >
      if [ -n "${SERVICE_ID:-}" ]; then
        stackhero service-delete --service="$SERVICE_ID" --confirm
        stackhero service-wait-for --service="$SERVICE_ID"
      fi
    - >
      if [ -n "${STACK_ID:-}" ]; then
        stackhero stack-delete --stack="$STACK_ID" --confirm
      fi

在 GitLab 中,資源清理會寫在 after_script 區塊。這個區塊無論 job 成功或失敗都會執行,確保您的 OpenSearch 資源被移除,避免產生不必要的費用。

在 GitLab,after_script 會在一個全新 shell中執行。為了處理這點,腳本會在 job 過程中將 service 與 stack 的 ID 寫入 deploy.env,並於清理前重新載入。如此即使 job 執行中途失敗,您的資源仍能被正確清除。

這就是 OpenSearch 的完整 CI 生命週期:建立 stack、加入服務、等待、取得認證、smoke test,並始終進行清理。每次 pipeline 執行都會獲得一個真實、隔離的服務,流程結束後不會有任何資源殘留。如需更多可用指令與非互動式 STACKHERO_TOKEN 認證說明,歡迎參考 完整 CLI 文件