TimescaleDB: GitHub Actions 及 GitLab CI

直接於您的 GitHub Actions 或 GitLab CI pipeline 啟動一個真實的 TimescaleDB 服務,執行測試,並自動清理資源

歡迎瀏覽 Stackhero 文件!

Stackhero 為您提供即開即用的 TimescaleDB cloud 方案,助您在數分鐘內快速上手。您可以享受到以下優勢:

  • 已預載所有頂級 插件,如 PostGISPgVector 等。
  • 方便使用的 PgAdmin 網頁介面,輕鬆管理資料庫。
  • 一鍵式 更新,讓您的部署保持最新狀態。
  • 在您專屬的 私有獨立 VM 上,確保 高效能強大安全性

如果您希望節省時間並簡化工作流程,Stackhero 的 TimescaleDB cloud hosting 將為您帶來流暢的體驗。只需 5 分鐘 即可試用!

本指南將帶您了解如何在 CI pipeline 中運行一個真實、專屬的 TimescaleDB 服務,無論您使用 GitHub ActionsGitLab CI。按照以下步驟,您可以在接近生產環境的條件下,針對實際的 TimescaleDB 實例測試您的程式碼,無需再依賴 mock 或模擬器。TimescaleDB is PostgreSQL extended for time-series workloads, so you get familiar SQL with the scale that metrics and events demand.

每次 pipeline 執行時,系統都會為您建立一個全新的 TimescaleDB 實例。這代表您的測試將與生產環境用戶所見的服務完全一致。整個流程會自動建立臨時 stack、加入 TimescaleDB、等待服務就緒、取得產生的認證資料、利用 psql 執行 smoke test,最後在流程結束時自動清理所有資源。

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

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

  1. 建立 token: 在您的 Stackhero 控制台,點擊右上角的個人頭像,進入 Your account,然後選擇 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 存取權的人都可能看到,甚至會出現在 build log。將其儲存為 CI 機密可確保 token 加密且遮蔽,保障您的安全。

以下是一個完整的腳本範例,涵蓋服務的全生命週期。您會看到只需幾個指令即可完成設定。您可於下方各平台區段複製對應的 YAML 範本。

#!/bin/bash
set -euo pipefail

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

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

# 1. 安裝 CLI 至 runner
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 postgresql-client

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

# 4. 加入 TimescaleDB 並取得其 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')
password=$(echo "$config" | jq -r '.configuration.password')

# 8. Smoke test:Run a trivial query against the database.
PGPASSWORD="$password" psql "host=$host port=5432 user=admin dbname=admin sslmode=require" -c "SELECT 1;"

echo "✅ TimescaleDB 已可由 CI 存取。"

清理步驟(刪除服務、等待刪除完成、再刪除 stack)會在下方各平台專屬區段說明。這樣可確保即使 smoke test 失敗也會自動清理。

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

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

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

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

name: CI with TimescaleDB

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      STACKHERO_TOKEN: ${{ secrets.STACKHERO_TOKEN }}
      STACK_NAME: ci-timescaledb-${{ github.run_id }}-${{ github.run_attempt }}
      INSTANCE: "10G"   # 如有需要可調整(見步驟 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 postgresql-client

      - name: 建立 TimescaleDB 服務
        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="timescaledb" \
            --instance="$INSTANCE" \
            --region="$REGION")
          echo "SERVICE_ID=$SERVICE_ID" >> "$GITHUB_ENV"
          stackhero service-wait-for --service="$SERVICE_ID"

      - name: 執行 TimescaleDB 測試
        run: |
          set -euo pipefail
          config=$(stackhero service-configuration-get --service="$SERVICE_ID" --format=json)
          host=$(echo "$config" | jq -r '.configuration.domain')
password=$(echo "$config" | jq -r '.configuration.password')
          # Run a trivial query against the database.
          PGPASSWORD="$password" psql "host=$host port=5432 user=admin dbname=admin sslmode=require" -c "SELECT 1;"
          echo "✅ TimescaleDB 已可由 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(),確保無論流程是否失敗都會執行,避免 TimescaleDB 實例未刪除而產生不必要的費用。

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

test:
  image: ubuntu:24.04
  variables:
    STACK_NAME: "ci-timescaledb-$CI_PIPELINE_ID-$CI_JOB_ID"
    INSTANCE: "10G"   # 如有需要可調整(見步驟 3)
    REGION: "europe"
    SERVICE_STORE: "timescaledb"
  # 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 postgresql-client
    - 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')
password=$(echo "$config" | jq -r '.configuration.password')
    # Run a trivial query against the database.
    - PGPASSWORD="$password" psql "host=$host port=5432 user=admin dbname=admin sslmode=require" -c "SELECT 1;"
    - echo "✅ TimescaleDB 已可由 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 成功與否都會執行,確保 TimescaleDB 資源被移除,避免產生不必要的費用。

在 GitLab,after_script 會於 全新 shell 執行。為處理此情境,腳本會於 job 過程中將 service 及 stack ID 寫入 deploy.env,於清理前再讀取。即使 job 執行中途失敗,您的資源仍會被正確清理。

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