ubicloud/.github/workflows/e2e.yml
Enes Cakir 958d9055e4 Allow downloading boot images from Cloudflare R2
We use our internal MinIO cluster to distribute images to our fleet. It
has a unique use case where we download a single large file repeatedly,
which impacts cluster performance and degrades the experience for other
users.

We decided to move image distribution to Cloudflare R2. This commit
enables generating presigned URLs for R2.
2025-08-27 12:43:23 +03:00

167 lines
7 KiB
YAML

name: E2E CI
permissions:
contents: read
on:
workflow_dispatch:
inputs:
test_cases:
description: 'Comma-separated list of test cases (vm)'
required: true
default: 'vm,github_runner_ubuntu_2404,github_runner_ubuntu_2204,postgres_standard,postgres_ha'
type: string
schedule:
- cron: '0 */2 * * *'
jobs:
run-ci:
if: vars.RUN_E2E == 'true'
runs-on: ubicloud-standard-4
environment: E2E-CI
timeout-minutes: 60
concurrency: e2e_environment
steps:
- name: Check out code
uses: actions/checkout@v5
- name: Set up Clover
uses: ./.github/actions/setup-clover
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: "package.json"
cache: "npm"
- name: Install node packages
run: npm ci
- name: Build assets
run: npm run prod
- name: Install cloudflared
run: curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && sudo dpkg -i cloudflared.deb
- name: Set cloudflared token
run: sudo cloudflared service install ${{ secrets.CLOUDFLARED_TOKEN }}
- name: Install mailpit
run: |
curl -sfL -m 90 -o mailpit.tar.gz https://github.com/axllent/mailpit/releases/download/v1.27.0/mailpit-linux-amd64.tar.gz
tar zxf mailpit.tar.gz
mv mailpit /usr/local/bin/
sudo systemd-run --setenv="MP_UI_AUTH=${{ secrets.MAIL_USER }}:${{ secrets.MAIL_PASSWORD }}" \
--setenv="MP_SMTP_AUTH=${{ secrets.MAIL_USER }}:${{ secrets.MAIL_PASSWORD }}" --setenv="MP_SMTP_AUTH_ALLOW_INSECURE=true" \
--unit mailpit -- mailpit
- name: Install foreman
run: gem install foreman
- name: Modify Procfile to add retry logic
run: |
sed -i "s/^\([^:]*\): \(.*\)/\1: bash -c 'for i in {1..4}; do \2 \&\& break || echo \"Attempt \$i failed, retrying...\"; sleep 1; done'/" Procfile
- name: Add e2e script to Procfile
run: |
test_cases="$(yq -r '[.[].name] | join(",")' config/e2e_test_cases.yml)"
if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ inputs.test_cases }}" ]]; then
test_cases="${{ inputs.test_cases }}"
fi
echo "Running e2e test cases: $test_cases"
echo "e2e: bin/e2e --test-cases=$test_cases" >> Procfile
- name: Run tests
env:
BASE_URL: https://${{ secrets.CLOUDFLARED_ADDRESS }}
CLOVER_DATABASE_URL: postgres:///clover_test?user=clover
RACK_ENV: production
IS_E2E: "true"
DISPATCHER_MAX_THREADS: 16
E2E_HETZNER_SERVER_ID: ${{ secrets.E2E_HETZNER_SERVER_ID }}
E2E_GITHUB_INSTALLATION_ID: ${{ secrets.E2E_GH_INSTALLATION_ID }}
HETZNER_SSH_PUBLIC_KEY: ${{ secrets.HETZNER_SSH_PUBLIC_KEY }}
HETZNER_SSH_PRIVATE_KEY: ${{ secrets.HETZNER_SSH_PRIVATE_KEY }}
HETZNER_USER: ${{ secrets.HETZNER_USER }}
HETZNER_PASSWORD: ${{ secrets.HETZNER_PASSWORD }}
UBICLOUD_IMAGES_BLOB_STORAGE_ENDPOINT: ${{ secrets.UBICLOUD_IMAGES_BLOB_STORAGE_ENDPOINT }}
UBICLOUD_IMAGES_BLOB_STORAGE_ACCESS_KEY: ${{ secrets.UBICLOUD_IMAGES_BLOB_STORAGE_ACCESS_KEY }}
UBICLOUD_IMAGES_BLOB_STORAGE_SECRET_KEY: ${{ secrets.UBICLOUD_IMAGES_BLOB_STORAGE_SECRET_KEY }}
UBICLOUD_IMAGES_BLOB_STORAGE_CERTS: ${{ secrets.UBICLOUD_IMAGES_BLOB_STORAGE_CERTS }}
UBICLOUD_IMAGES_R2_BUCKET_NAME: ${{ secrets.UBICLOUD_IMAGES_R2_BUCKET_NAME }}
UBICLOUD_IMAGES_R2_ENDPOINT: ${{ secrets.UBICLOUD_IMAGES_R2_ENDPOINT }}
UBICLOUD_IMAGES_R2_ACCESS_KEY: ${{ secrets.UBICLOUD_IMAGES_R2_ACCESS_KEY }}
UBICLOUD_IMAGES_R2_SECRET_KEY: ${{ secrets.UBICLOUD_IMAGES_R2_SECRET_KEY }}
GITHUB_APP_NAME: ${{ secrets.GH_APP_NAME }}
GITHUB_APP_ID: ${{ secrets.GH_APP_ID }}
GITHUB_APP_CLIENT_ID: ${{ secrets.GH_APP_CLIENT_ID }}
GITHUB_APP_CLIENT_SECRET: ${{ secrets.GH_APP_CLIENT_SECRET }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.GH_APP_PRIVATE_KEY }}
GITHUB_APP_WEBHOOK_SECRET: ${{ secrets.GH_APP_WEBHOOK_SECRET }}
GITHUB_RUNNER_SERVICE_PROJECT_ID: "89841457-35a2-8ed2-a88a-424ea5ddd83b"
GITHUB_CACHE_BLOB_STORAGE_ENDPOINT: ${{ secrets.GH_CACHE_BLOB_STORAGE_ENDPOINT }}
GITHUB_CACHE_BLOB_STORAGE_REGION: ${{ secrets.GH_CACHE_BLOB_STORAGE_REGION }}
GITHUB_CACHE_BLOB_STORAGE_ACCESS_KEY: ${{ secrets.GH_CACHE_BLOB_STORAGE_ACCESS_KEY }}
GITHUB_CACHE_BLOB_STORAGE_SECRET_KEY: ${{ secrets.GH_CACHE_BLOB_STORAGE_SECRET_KEY }}
GITHUB_CACHE_BLOB_STORAGE_ACCOUNT_ID: ${{ secrets.GH_CACHE_BLOB_STORAGE_ACCOUNT_ID }}
GITHUB_CACHE_BLOB_STORAGE_API_KEY: ${{ secrets.GH_CACHE_BLOB_STORAGE_API_KEY }}
POSTGRES_SERVICE_PROJECT_ID: "546a1ed8-53e5-86d2-966c-fb782d2ae5ab"
MINIO_SERVICE_PROJECT_ID: "37ad2a8d-0220-4e8b-a67f-38db95d6c657"
VM_POOL_PROJECT_ID: "e4b93fb7-5125-8ad2-9d29-730ff4506bc3"
MAIL_FROM: test@example.com
SMTP_USER: ${{ secrets.MAIL_USER }}
SMTP_PASSWORD: ${{ secrets.MAIL_PASSWORD }}
SMTP_HOSTNAME: localhost
SMTP_PORT: 1025
SMTP_TLS: false
STRIPE_PUBLIC_KEY: ${{ secrets.STRIPE_PUBLIC_KEY }}
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
VHOST_BLOCK_BACKEND_VERSION: v0.2.0
run: |
set -o pipefail
timeout 55m foreman start -m all=1,respirate=2 | tee foreman.log | grep --line-buffered -F "e2e.1"
- name: Print logs
if: always()
run: grep -h -v -E "sleep_duration_sec|monitor.1" foreman.log
- name: Extract image download time
if: always()
id: extract_download
run: |
download_time="$(grep "VmHost.wait_download_boot_images" foreman.log | cut -d'|' -f2 | tail -1)"
echo "### Image downloaded in $download_time" >> $GITHUB_STEP_SUMMARY
echo "DOWNLOAD_TIME=$download_time" >> $GITHUB_OUTPUT
- name: Upload logs
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-${{ github.run_id }}-logs
path: foreman.log
- name: Send notification if failed
if: ${{ failure() && github.ref_name == 'main' }}
uses: slackapi/slack-github-action@v2.1.1
with:
webhook: ${{ secrets.SLACK_WEBHOOK_PAGER_URL }}
webhook-type: incoming-webhook
payload: |
text: "*E2E Tests Failed* :this-is-fine-fire:"
attachments:
- color: "E33122"
fields:
- title: "Event"
short: true
value: "${{ github.event_name }}"
- title: "Reference"
short: true
value: "<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.ref_name }}>"
- title: "Action"
short: true
value: "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>"
- title: "Download Time"
short: true
value: "${{ steps.extract_download.outputs.DOWNLOAD_TIME }}"