quality / commitlint (push) Skipped
CD / update-wiki (push) Successful in 6s
quality / changes (push) Successful in 8s
quality / docker-check (push) Skipped
quality / web (push) Successful in 51s
quality / api (push) Successful in 45s
CD / quality (push) Successful in 1m47s
CD / publish (push) Successful in 1m37s
Co-authored-by: Cursor <cursoragent@cursor.com>
297 lines
9.7 KiB
YAML
297 lines
9.7 KiB
YAML
# Quality gates (reusable). Callers: ci.yaml (PR), cd.yaml (push main).
|
|
name: quality
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
is_pull_request:
|
|
type: boolean
|
|
required: true
|
|
base_sha:
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
head_sha:
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
before_sha:
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
allow_registry_login:
|
|
type: boolean
|
|
required: false
|
|
default: false
|
|
secrets:
|
|
ACTIONS_PAT:
|
|
required: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
changes:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
web: ${{ steps.detect.outputs.web }}
|
|
api: ${{ steps.detect.outputs.api }}
|
|
docker: ${{ steps.detect.outputs.docker }}
|
|
steps:
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
# Push may contain several commits; github.event.before is then
|
|
# more than one parent away. fetch-depth: 2 only has HEAD~1.
|
|
fetch-depth: 0
|
|
- id: detect
|
|
name: Detect changed paths per module
|
|
env:
|
|
IS_PR: ${{ inputs.is_pull_request }}
|
|
BASE_SHA: ${{ inputs.base_sha }}
|
|
HEAD_SHA: ${{ inputs.head_sha }}
|
|
BEFORE_SHA: ${{ inputs.before_sha }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
web=false
|
|
api=false
|
|
docker=false
|
|
|
|
set_all_flags_true() {
|
|
web=true
|
|
api=true
|
|
docker=true
|
|
}
|
|
|
|
write_outputs() {
|
|
for v in web api docker; do
|
|
eval "echo \"\$v=\$$v\"" >> "$GITHUB_OUTPUT"
|
|
done
|
|
}
|
|
|
|
has_commit() {
|
|
git cat-file -e "${1}^{commit}" 2>/dev/null
|
|
}
|
|
|
|
if [ "$IS_PR" = "true" ]; then
|
|
FILES="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
|
|
else
|
|
after="${HEAD_SHA:-$(git rev-parse HEAD)}"
|
|
before="$BEFORE_SHA"
|
|
if [ -n "$before" ] && [ "$before" != "0000000000000000000000000000000000000000" ] && has_commit "$before"; then
|
|
FILES="$(git diff --name-only "$before" "$after")"
|
|
elif git rev-parse --verify HEAD~1 >/dev/null 2>&1; then
|
|
FILES="$(git diff --name-only HEAD~1 HEAD)"
|
|
else
|
|
set_all_flags_true
|
|
write_outputs
|
|
echo "No parent commit — full pipeline (all modules)"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$(printf '%s' "$FILES" | tr -d '[:space:]')" ]; then
|
|
set_all_flags_true
|
|
write_outputs
|
|
echo "Empty diff — full pipeline fallback"
|
|
exit 0
|
|
fi
|
|
|
|
full_pipeline=false
|
|
|
|
while IFS= read -r f || [ -n "${f:-}" ]; do
|
|
[ -z "${f:-}" ] && continue
|
|
case "$f" in
|
|
.gitea/workflows/*|scripts/*)
|
|
full_pipeline=true
|
|
;;
|
|
.cursor/*|.claude/*|.codegraph/*|.agents/*)
|
|
;;
|
|
*.md|AGENTS.md)
|
|
;;
|
|
apps/web/README.md|apps/web/components.json|packages/ui/components.json)
|
|
;;
|
|
apps/web/*|packages/ui/*)
|
|
web=true
|
|
;;
|
|
apps/api/*|packages/db/*)
|
|
api=true
|
|
;;
|
|
packages/shared/*)
|
|
web=true
|
|
api=true
|
|
;;
|
|
deploy/compose/*|deploy/docker/*|.dockerignore|docker-compose.yml)
|
|
docker=true
|
|
;;
|
|
docs/*)
|
|
;;
|
|
package.json|pnpm-lock.yaml|pnpm-workspace.yaml|turbo.json|.releaserc.json|commitlint.config.cjs)
|
|
full_pipeline=true
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
done <<< "$FILES"
|
|
|
|
if $full_pipeline; then
|
|
set_all_flags_true
|
|
fi
|
|
|
|
write_outputs
|
|
|
|
echo "Changed files (first 30):"
|
|
printf '%s\n' "$FILES" | head -n 30
|
|
echo "--- flags ---"
|
|
echo "web=$web api=$api docker=$docker full_pipeline=$full_pipeline"
|
|
|
|
web:
|
|
needs: [changes]
|
|
if: needs.changes.outputs.web == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "22"
|
|
- name: Export cache paths
|
|
run: sh scripts/ci/export-cache-env.sh
|
|
- id: pnpm-hash
|
|
run: echo "key=$(sha256sum pnpm-lock.yaml | awk '{print $1}')" >> "$GITHUB_OUTPUT"
|
|
- id: pnpm-cache
|
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
with:
|
|
path: |
|
|
${{ env.PNPM_STORE_DIR }}
|
|
${{ env.COREPACK_HOME }}
|
|
node_modules
|
|
apps/web/node_modules
|
|
apps/api/node_modules
|
|
packages/ui/node_modules
|
|
packages/shared/node_modules
|
|
packages/db/node_modules
|
|
key: pnpm-${{ runner.os }}-${{ steps.pnpm-hash.outputs.key }}
|
|
restore-keys: |
|
|
pnpm-${{ runner.os }}-
|
|
- name: pnpm install, lint, test, build
|
|
env:
|
|
PNPM_CACHE_HIT: ${{ steps.pnpm-cache.outputs.cache-hit }}
|
|
run: |
|
|
set -euxo pipefail
|
|
sh scripts/ci/pnpm-ci.sh
|
|
pnpm --filter web lint
|
|
pnpm exec turbo run test --filter=web
|
|
pnpm exec turbo run build --filter=web
|
|
|
|
api:
|
|
needs: [changes]
|
|
if: needs.changes.outputs.api == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "22"
|
|
- name: Export cache paths
|
|
run: sh scripts/ci/export-cache-env.sh
|
|
- id: pnpm-hash
|
|
run: echo "key=$(sha256sum pnpm-lock.yaml | awk '{print $1}')" >> "$GITHUB_OUTPUT"
|
|
- id: pnpm-cache
|
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
with:
|
|
path: |
|
|
${{ env.PNPM_STORE_DIR }}
|
|
${{ env.COREPACK_HOME }}
|
|
node_modules
|
|
apps/web/node_modules
|
|
apps/api/node_modules
|
|
packages/ui/node_modules
|
|
packages/shared/node_modules
|
|
packages/db/node_modules
|
|
key: pnpm-${{ runner.os }}-${{ steps.pnpm-hash.outputs.key }}
|
|
restore-keys: |
|
|
pnpm-${{ runner.os }}-
|
|
- name: pnpm install, test, build
|
|
env:
|
|
PNPM_CACHE_HIT: ${{ steps.pnpm-cache.outputs.cache-hit }}
|
|
run: |
|
|
set -euxo pipefail
|
|
sh scripts/ci/pnpm-ci.sh
|
|
pnpm exec turbo run test --filter=@cfdm/api
|
|
pnpm exec turbo run build --filter=@cfdm/api
|
|
|
|
commitlint:
|
|
if: inputs.is_pull_request
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
fetch-depth: 0
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "22"
|
|
- name: Export cache paths
|
|
run: sh scripts/ci/export-cache-env.sh
|
|
- id: pnpm-hash
|
|
run: echo "key=$(sha256sum pnpm-lock.yaml | awk '{print $1}')" >> "$GITHUB_OUTPUT"
|
|
- id: pnpm-cache
|
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
with:
|
|
path: |
|
|
${{ env.PNPM_STORE_DIR }}
|
|
${{ env.COREPACK_HOME }}
|
|
node_modules
|
|
apps/web/node_modules
|
|
apps/api/node_modules
|
|
packages/ui/node_modules
|
|
packages/shared/node_modules
|
|
packages/db/node_modules
|
|
key: pnpm-${{ runner.os }}-${{ steps.pnpm-hash.outputs.key }}
|
|
restore-keys: |
|
|
pnpm-${{ runner.os }}-
|
|
- name: Lint commit messages
|
|
env:
|
|
BASE_SHA: ${{ inputs.base_sha }}
|
|
HEAD_SHA: ${{ inputs.head_sha }}
|
|
PNPM_CACHE_HIT: ${{ steps.pnpm-cache.outputs.cache-hit }}
|
|
run: |
|
|
set -euxo pipefail
|
|
sh scripts/ci/pnpm-ci.sh
|
|
pnpm exec commitlint --from "$BASE_SHA" --to "$HEAD_SHA"
|
|
|
|
docker-check:
|
|
needs: [changes]
|
|
if: inputs.is_pull_request && needs.changes.outputs.docker == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
|
with:
|
|
name: cfdm
|
|
driver: docker-container
|
|
cleanup: false
|
|
- name: Log in to Gitea Registry
|
|
if: inputs.allow_registry_login
|
|
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
|
with:
|
|
registry: git.shx.one
|
|
username: ${{ gitea.actor }}
|
|
password: ${{ secrets.ACTIONS_PAT }}
|
|
- name: bake --print
|
|
working-directory: deploy/docker
|
|
env:
|
|
BUILDX_BAKE_ENTITLEMENTS_FS: "0"
|
|
BUILDX_BAKE_FILE_RELATIVE_PATHS: "1"
|
|
run: docker buildx bake --allow=fs.read="${{ github.workspace }}" -f docker-bake.hcl --print default
|
|
- name: bake (no push)
|
|
if: inputs.allow_registry_login
|
|
working-directory: deploy/docker
|
|
env:
|
|
BUILDX_BAKE_ENTITLEMENTS_FS: "0"
|
|
BUILDX_BAKE_FILE_RELATIVE_PATHS: "1"
|
|
run: |
|
|
set -euxo pipefail
|
|
owner_lc="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')"
|
|
export CACHE_REF_NODE="git.shx.one/${owner_lc}/cfdm-buildcache:node-buildcache"
|
|
docker buildx bake --allow=fs.read="${{ github.workspace }}" -f docker-bake.hcl default
|