Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 717f239f1b | |||
| 014949e6b1 | |||
| 531a2024b0 |
@@ -16,46 +16,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/{os.environ['GITHUB_SHA']}.tar.gz"
|
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
|
||||||
last_err = None
|
|
||||||
for attempt in range(5):
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
top_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == top_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(top_prefix):
|
|
||||||
member.name = name[len(top_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Auto merge develop PRs
|
- name: Auto merge develop PRs
|
||||||
run: |
|
run: |
|
||||||
bash scripts/auto_merge_prs.sh develop
|
bash scripts/auto_merge_prs.sh develop
|
||||||
|
|||||||
+50
-276
@@ -15,6 +15,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- develop
|
- develop
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -36,46 +37,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
|
||||||
last_err = None
|
|
||||||
for attempt in range(5):
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Verify CI environment
|
- name: Verify CI environment
|
||||||
shell: sh
|
shell: sh
|
||||||
run: |
|
run: |
|
||||||
@@ -84,6 +46,14 @@ jobs:
|
|||||||
python3 -m pip --version
|
python3 -m pip --version
|
||||||
echo "CI environment is ready"
|
echo "CI environment is ready"
|
||||||
|
|
||||||
|
- name: Cache pip dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pip
|
||||||
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pip-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
shell: sh
|
shell: sh
|
||||||
run: |
|
run: |
|
||||||
@@ -281,45 +251,14 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
- name: Cache npm dependencies
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
uses: actions/cache@v3
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
with:
|
||||||
last_err = None
|
path: ~/.npm
|
||||||
for attempt in range(5):
|
key: ${{ runner.os }}-npm-${{ hashFiles('apps/web/package-lock.json') }}
|
||||||
try:
|
restore-keys: |
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
${{ runner.os }}-npm-
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
shell: sh
|
shell: sh
|
||||||
@@ -327,6 +266,7 @@ jobs:
|
|||||||
set -eu
|
set -eu
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v "$PWD:/workspace" \
|
-v "$PWD:/workspace" \
|
||||||
|
-v "$HOME/.npm:/root/.npm" \
|
||||||
-w /workspace/apps/web \
|
-w /workspace/apps/web \
|
||||||
docker.m.daocloud.io/library/node:20 \
|
docker.m.daocloud.io/library/node:20 \
|
||||||
sh -lc 'npm ci'
|
sh -lc 'npm ci'
|
||||||
@@ -385,45 +325,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'INNERPY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
|
||||||
last_err = None
|
|
||||||
for attempt in range(5):
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
INNERPY
|
|
||||||
|
|
||||||
- name: Build and push all images to Gitea Registry
|
- name: Build and push all images to Gitea Registry
|
||||||
shell: sh
|
shell: sh
|
||||||
env:
|
env:
|
||||||
@@ -516,45 +418,15 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
- name: Cache npm dependencies
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
uses: actions/cache@v3
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
with:
|
||||||
last_err = None
|
path: ~/.npm
|
||||||
for attempt in range(5):
|
key: ${{ runner.os }}-npm-${{ hashFiles('apps/web/package-lock.json') }}
|
||||||
try:
|
restore-keys: |
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
${{ runner.os }}-npm-
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
- name: Run Playwright E2E on staging
|
- name: Run Playwright E2E on staging
|
||||||
shell: sh
|
shell: sh
|
||||||
run: |
|
run: |
|
||||||
@@ -565,6 +437,7 @@ jobs:
|
|||||||
-e E2E_BROWSER_CHANNEL=chromium \
|
-e E2E_BROWSER_CHANNEL=chromium \
|
||||||
-e PLAYWRIGHT_HEADLESS=1 \
|
-e PLAYWRIGHT_HEADLESS=1 \
|
||||||
-v "$PWD:/workspace" \
|
-v "$PWD:/workspace" \
|
||||||
|
-v "$HOME/.npm:/root/.npm" \
|
||||||
-w /workspace/apps/web \
|
-w /workspace/apps/web \
|
||||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||||
sh -lc "npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts"
|
sh -lc "npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts"
|
||||||
@@ -583,45 +456,15 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
- name: Cache npm dependencies
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
uses: actions/cache@v3
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
with:
|
||||||
last_err = None
|
path: ~/.npm
|
||||||
for attempt in range(5):
|
key: ${{ runner.os }}-npm-${{ hashFiles('apps/web/package-lock.json') }}
|
||||||
try:
|
restore-keys: |
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
${{ runner.os }}-npm-
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
- name: Run API integration tests on staging
|
- name: Run API integration tests on staging
|
||||||
shell: sh
|
shell: sh
|
||||||
run: |
|
run: |
|
||||||
@@ -630,6 +473,7 @@ jobs:
|
|||||||
-e E2E_BASE_URL=https://staging.xiaoxiajianji.com \
|
-e E2E_BASE_URL=https://staging.xiaoxiajianji.com \
|
||||||
-e E2E_API_BASE=https://staging-api.xiaoxiajianji.com/api/v1 \
|
-e E2E_API_BASE=https://staging-api.xiaoxiajianji.com/api/v1 \
|
||||||
-v "$PWD:/workspace" \
|
-v "$PWD:/workspace" \
|
||||||
|
-v "$HOME/.npm:/root/.npm" \
|
||||||
-w /workspace/apps/web \
|
-w /workspace/apps/web \
|
||||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||||
sh -lc 'npm ci && npx playwright test --reporter=line e2e/test_auth.spec.ts e2e/test_asset.spec.ts e2e/test_project.spec.ts'
|
sh -lc 'npm ci && npx playwright test --reporter=line e2e/test_auth.spec.ts e2e/test_asset.spec.ts e2e/test_project.spec.ts'
|
||||||
@@ -650,46 +494,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
|
||||||
last_err = None
|
|
||||||
for attempt in range(5):
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Build and push all images (api + worker + web, with buildx cache)
|
- name: Build and push all images (api + worker + web, with buildx cache)
|
||||||
shell: sh
|
shell: sh
|
||||||
env:
|
env:
|
||||||
@@ -793,46 +598,14 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
- name: Cache npm dependencies
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
uses: actions/cache@v3
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
with:
|
||||||
# Retry up to 5 times with backoff for transient 5xx errors
|
path: ~/.npm
|
||||||
last_err = None
|
key: ${{ runner.os }}-npm-${{ hashFiles('apps/web/package-lock.json') }}
|
||||||
for attempt in range(5):
|
restore-keys: |
|
||||||
try:
|
${{ runner.os }}-npm-
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Run production browser E2E
|
- name: Run production browser E2E
|
||||||
shell: sh
|
shell: sh
|
||||||
@@ -844,6 +617,7 @@ jobs:
|
|||||||
-e E2E_BROWSER_CHANNEL=chromium \
|
-e E2E_BROWSER_CHANNEL=chromium \
|
||||||
-e PLAYWRIGHT_HEADLESS=1 \
|
-e PLAYWRIGHT_HEADLESS=1 \
|
||||||
-v "$PWD:/workspace" \
|
-v "$PWD:/workspace" \
|
||||||
|
-v "$HOME/.npm:/root/.npm" \
|
||||||
-w /workspace/apps/web \
|
-w /workspace/apps/web \
|
||||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||||
sh -lc 'npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts e2e/core-titles.spec.ts'
|
sh -lc 'npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts e2e/core-titles.spec.ts'
|
||||||
|
|||||||
@@ -24,46 +24,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
|
||||||
last_err = None
|
|
||||||
for attempt in range(5):
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Production health check & smoke test
|
- name: Production health check & smoke test
|
||||||
id: smoke
|
id: smoke
|
||||||
shell: sh
|
shell: sh
|
||||||
@@ -121,46 +82,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
|
||||||
last_err = None
|
|
||||||
for attempt in range(5):
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Run API smoke test on staging
|
- name: Run API smoke test on staging
|
||||||
id: smoke
|
id: smoke
|
||||||
shell: sh
|
shell: sh
|
||||||
@@ -258,45 +180,14 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
python3 - <<'PY'
|
bash scripts/ci_checkout.sh
|
||||||
import io, os, tarfile, time, urllib.request, urllib.error
|
- name: Cache npm dependencies
|
||||||
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
|
uses: actions/cache@v3
|
||||||
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
|
with:
|
||||||
last_err = None
|
path: ~/.npm
|
||||||
for attempt in range(5):
|
key: ${{ runner.os }}-npm-${{ hashFiles('apps/web/package-lock.json') }}
|
||||||
try:
|
restore-keys: |
|
||||||
with urllib.request.urlopen(request, timeout=120) as response:
|
${{ runner.os }}-npm-
|
||||||
archive = response.read()
|
|
||||||
break
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
last_err = e
|
|
||||||
if e.code >= 500 and attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
if attempt < 4:
|
|
||||||
wait = 2 ** attempt
|
|
||||||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
|
||||||
time.sleep(wait)
|
|
||||||
continue
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
raise last_err
|
|
||||||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
|
||||||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
|
||||||
for member in tar.getmembers():
|
|
||||||
name = member.name
|
|
||||||
if name == root_prefix[:-1]:
|
|
||||||
continue
|
|
||||||
if name.startswith(root_prefix):
|
|
||||||
member.name = name[len(root_prefix):]
|
|
||||||
if member.name:
|
|
||||||
tar.extract(member, '.')
|
|
||||||
PY
|
|
||||||
|
|
||||||
- name: Run Playwright E2E on staging
|
- name: Run Playwright E2E on staging
|
||||||
id: e2e
|
id: e2e
|
||||||
@@ -310,6 +201,7 @@ jobs:
|
|||||||
-e E2E_BROWSER_CHANNEL=chromium \
|
-e E2E_BROWSER_CHANNEL=chromium \
|
||||||
-e PLAYWRIGHT_HEADLESS=1 \
|
-e PLAYWRIGHT_HEADLESS=1 \
|
||||||
-v "$PWD:/workspace" \
|
-v "$PWD:/workspace" \
|
||||||
|
-v "$HOME/.npm:/root/.npm" \
|
||||||
-w /workspace/apps/web \
|
-w /workspace/apps/web \
|
||||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||||
sh -lc 'npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts e2e/core-titles.spec.ts' 2>&1 | tee /tmp/staging-e2e.log
|
sh -lc 'npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts e2e/core-titles.spec.ts' 2>&1 | tee /tmp/staging-e2e.log
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# CI Checkout script - 从 Gitea API 下载源码 tar 包并解压
|
||||||
|
# 用法: ci_checkout.sh [repo_api_base] [ref] [target_dir] [token]
|
||||||
|
# repo_api_base: 仓库 API 基础 URL,如 https://git.xiaoxiajianji.com/api/v1/repos/xiaoxia/xiaoxia-saas
|
||||||
|
# ref: commit SHA 或分支名
|
||||||
|
# target_dir: 目标目录(默认当前目录)
|
||||||
|
# token: API token
|
||||||
|
# 所有参数均可省略,将从 Gitea Actions 环境变量中读取
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# ── 参数解析 ──────────────────────────────────────────────────
|
||||||
|
REPO_API_BASE="${1:-}"
|
||||||
|
REF="${2:-}"
|
||||||
|
TARGET_DIR="${3:-.}"
|
||||||
|
TOKEN="${4:-}"
|
||||||
|
|
||||||
|
# 从环境变量补全默认值(兼容 Gitea Actions)
|
||||||
|
if [ -z "$REPO_API_BASE" ]; then
|
||||||
|
REPO_API_BASE="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}"
|
||||||
|
fi
|
||||||
|
if [ -z "$REF" ]; then
|
||||||
|
REF="${GITHUB_SHA}"
|
||||||
|
fi
|
||||||
|
if [ -z "$TOKEN" ]; then
|
||||||
|
TOKEN="${GITHUB_TOKEN:-}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$REPO_API_BASE" ] || [ -z "$REF" ]; then
|
||||||
|
echo "ERROR: repo API base and ref are required" >&2
|
||||||
|
echo "Usage: $0 [repo_api_base] [ref] [target_dir] [token]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── 下载并解压 ────────────────────────────────────────────────
|
||||||
|
ARCHIVE_URL="${REPO_API_BASE}/archive/${REF}.tar.gz"
|
||||||
|
|
||||||
|
echo "Checkout: ${ARCHIVE_URL}"
|
||||||
|
echo "Target dir: ${TARGET_DIR}"
|
||||||
|
|
||||||
|
mkdir -p "${TARGET_DIR}"
|
||||||
|
|
||||||
|
# 通过环境变量传递给 Python
|
||||||
|
_CHECKOUT_URL="${ARCHIVE_URL}" \
|
||||||
|
_CHECKOUT_TOKEN="${TOKEN}" \
|
||||||
|
_CHECKOUT_TARGET_DIR="${TARGET_DIR}" \
|
||||||
|
python3 - <<'PY'
|
||||||
|
import io, os, tarfile, time, urllib.request, urllib.error
|
||||||
|
|
||||||
|
url = os.environ['_CHECKOUT_URL']
|
||||||
|
token = os.environ.get('_CHECKOUT_TOKEN', '')
|
||||||
|
target_dir = os.environ['_CHECKOUT_TARGET_DIR']
|
||||||
|
|
||||||
|
headers = {}
|
||||||
|
if token:
|
||||||
|
headers["Authorization"] = f"token {token}"
|
||||||
|
|
||||||
|
request = urllib.request.Request(url, headers=headers)
|
||||||
|
|
||||||
|
last_err = None
|
||||||
|
for attempt in range(5):
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(request, timeout=120) as response:
|
||||||
|
archive = response.read()
|
||||||
|
break
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
last_err = e
|
||||||
|
if e.code >= 500 and attempt < 4:
|
||||||
|
wait = 2 ** attempt
|
||||||
|
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
||||||
|
time.sleep(wait)
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
last_err = e
|
||||||
|
if attempt < 4:
|
||||||
|
wait = 2 ** attempt
|
||||||
|
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
||||||
|
time.sleep(wait)
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
raise last_err
|
||||||
|
|
||||||
|
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
||||||
|
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
||||||
|
for member in tar.getmembers():
|
||||||
|
name = member.name
|
||||||
|
if name == root_prefix[:-1]:
|
||||||
|
continue
|
||||||
|
if name.startswith(root_prefix):
|
||||||
|
member.name = name[len(root_prefix):]
|
||||||
|
if member.name:
|
||||||
|
tar.extract(member, target_dir)
|
||||||
|
|
||||||
|
print("Checkout complete.")
|
||||||
|
PY
|
||||||
Reference in New Issue
Block a user