054a0fa7db
* refactor: Add dedicated setup-db job to eliminate cache race condition - Create new setup-db.yml workflow that runs cache-db action - Update pr.yml to add setup-db job that runs before all E2E jobs - Update integration-test, e2e, e2e-api-v2, e2e-app-store, e2e-embed, and e2e-embed-react jobs to depend on setup-db instead of build-api-v1 - Add setup-db to required job needs list and result check This eliminates the race condition where multiple jobs could try to write to the same database cache simultaneously. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * refactor: Remove DB parts from api-v1-production-build.yml The database setup is now handled by the dedicated setup-db job, so the postgres service and cache-db action are no longer needed in the API v1 build workflow. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * Apply suggestion from @keithwillcode * Made integration tests dependency consistent * refactor: Remove unnecessary env vars from setup-db.yml Only keep the env vars needed for database setup: - CALENDSO_ENCRYPTION_KEY (for db-seed) - DATABASE_URL / DATABASE_DIRECT_URL (for database connection) - TURBO_TOKEN / TURBO_TEAM (for turbo caching) Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: Add back E2E_TEST_CALCOM_QA_* env vars needed by db-seed These env vars are used by scripts/seed.ts to create the QA user with Google Calendar credentials during database seeding. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: Restore postgres service and cache-db to api-v1-production-build.yml The API v1 build still needs a database to run properly. Restored the postgres service and cache-db action, and added dependency on setup-db so it waits for the database cache to be created first. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * E2E for API v2 no longer waiting on API v2 build * Reordering the jobs by dependencies * add GOOGLE_API_CREDENTIALS env var to setup db * Added back all env vars to setup-db * fix: Include commit SHA in cache-db key to invalidate cache on new commits Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * refactor: Strip back setup-db.yml env vars to minimal set needed for db-seed Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
292 lines
9.4 KiB
YAML
292 lines
9.4 KiB
YAML
name: PR Update
|
|
|
|
on:
|
|
pull_request_target:
|
|
types: [opened, synchronize, reopened]
|
|
branches:
|
|
- main
|
|
- gh-actions-test-branch
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
actions: write
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
prepare:
|
|
name: Prepare
|
|
runs-on: buildjet-2vcpu-ubuntu-2204
|
|
permissions:
|
|
pull-requests: read
|
|
outputs:
|
|
has-files-requiring-all-checks: ${{ steps.filter.outputs.has-files-requiring-all-checks }}
|
|
has_companion: ${{ steps.filter.outputs.has_companion }}
|
|
commit-sha: ${{ steps.get_sha.outputs.commit-sha }}
|
|
run-e2e: ${{ steps.check-if-pr-has-label.outputs.run-e2e == 'true' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: ./.github/actions/dangerous-git-checkout
|
|
- uses: dorny/paths-filter@v3
|
|
id: filter
|
|
with:
|
|
predicate-quantifier: "every"
|
|
filters: |
|
|
has-files-requiring-all-checks:
|
|
- '**'
|
|
- '!companion/**'
|
|
- '!**/*.md'
|
|
- '!**/*.mdx'
|
|
- '!.github/CODEOWNERS'
|
|
- '!docs/**'
|
|
- '!help/**'
|
|
- '!apps/web/public/static/locales/**/common.json'
|
|
- '!i18n.lock'
|
|
has_companion:
|
|
- "companion/**"
|
|
- name: Get Latest Commit SHA
|
|
id: get_sha
|
|
run: |
|
|
echo "commit-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
|
- name: Check if PR exists with ready-for-e2e label for this SHA
|
|
id: check-if-pr-has-label
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
let labels = [];
|
|
let prNumber = null;
|
|
|
|
if (context.payload.pull_request) {
|
|
prNumber = context.payload.pull_request.number;
|
|
} else {
|
|
try {
|
|
const sha = '${{ steps.get_sha.outputs.commit-sha }}';
|
|
console.log('sha', sha);
|
|
const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
commit_sha: sha
|
|
});
|
|
|
|
if (prs.length === 0) {
|
|
core.setOutput('run-e2e', false);
|
|
console.log(`No pull requests found for commit SHA ${sha}`);
|
|
return;
|
|
}
|
|
|
|
prNumber = prs[0].number;
|
|
}
|
|
catch (e) {
|
|
core.setOutput('run-e2e', false);
|
|
console.log(e);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Always fetch fresh PR data to get current labels
|
|
// This avoids stale label data from event payloads
|
|
try {
|
|
const { data: pr } = await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber
|
|
});
|
|
|
|
console.log(`PR number: ${pr.number}`);
|
|
console.log(`PR title: ${pr.title}`);
|
|
console.log(`PR state: ${pr.state}`);
|
|
console.log(`PR URL: ${pr.html_url}`);
|
|
|
|
labels = pr.labels;
|
|
}
|
|
catch (e) {
|
|
core.setOutput('run-e2e', false);
|
|
console.log(e);
|
|
return;
|
|
}
|
|
|
|
const labelFound = labels.map(l => l.name).includes('ready-for-e2e');
|
|
console.log('Found the label?', labelFound);
|
|
core.setOutput('run-e2e', labelFound);
|
|
|
|
deps:
|
|
name: Install dependencies
|
|
needs: [prepare]
|
|
if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/yarn-install.yml
|
|
|
|
type-check:
|
|
name: Type check
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/check-types.yml
|
|
secrets: inherit
|
|
|
|
lint:
|
|
name: Linters
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/lint.yml
|
|
secrets: inherit
|
|
|
|
unit-test:
|
|
name: Tests
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/unit-tests.yml
|
|
secrets: inherit
|
|
|
|
setup-db:
|
|
name: Setup Database
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/setup-db.yml
|
|
with:
|
|
COMMIT_SHA: ${{ needs.prepare.outputs.commit-sha }}
|
|
secrets: inherit
|
|
|
|
build-api-v1:
|
|
name: Production builds
|
|
needs: [prepare, deps, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/api-v1-production-build.yml
|
|
secrets: inherit
|
|
|
|
build-api-v2:
|
|
name: Production builds
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/api-v2-production-build.yml
|
|
secrets: inherit
|
|
|
|
build-atoms:
|
|
name: Production builds
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/atoms-production-build.yml
|
|
secrets: inherit
|
|
|
|
build-docs:
|
|
name: Production builds
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/docs-build.yml
|
|
secrets: inherit
|
|
|
|
build-companion:
|
|
name: Companion builds
|
|
needs: [prepare]
|
|
if: needs.prepare.outputs.has_companion == 'true'
|
|
uses: ./.github/workflows/companion-build.yml
|
|
secrets: inherit
|
|
|
|
build:
|
|
name: Production builds
|
|
needs: [prepare, deps]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/production-build-without-database.yml
|
|
secrets: inherit
|
|
|
|
integration-test:
|
|
name: Tests
|
|
needs: [prepare, build, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/integration-tests.yml
|
|
secrets: inherit
|
|
|
|
e2e:
|
|
name: Tests
|
|
needs: [prepare, build, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/e2e.yml
|
|
secrets: inherit
|
|
|
|
e2e-api-v2:
|
|
name: Tests
|
|
needs: [prepare, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/e2e-api-v2.yml
|
|
secrets: inherit
|
|
|
|
e2e-app-store:
|
|
name: Tests
|
|
needs: [prepare, build, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/e2e-app-store.yml
|
|
secrets: inherit
|
|
|
|
e2e-embed:
|
|
name: Tests
|
|
needs: [prepare, build, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/e2e-embed.yml
|
|
secrets: inherit
|
|
|
|
e2e-embed-react:
|
|
name: Tests
|
|
needs: [prepare, build, setup-db]
|
|
if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }}
|
|
uses: ./.github/workflows/e2e-embed-react.yml
|
|
secrets: inherit
|
|
|
|
analyze:
|
|
name: Analyze Build
|
|
needs: [build]
|
|
uses: ./.github/workflows/nextjs-bundle-analysis.yml
|
|
secrets: inherit
|
|
|
|
required:
|
|
needs:
|
|
[
|
|
prepare,
|
|
lint,
|
|
type-check,
|
|
unit-test,
|
|
integration-test,
|
|
build,
|
|
build-api-v1,
|
|
build-api-v2,
|
|
build-atoms,
|
|
build-docs,
|
|
build-companion,
|
|
setup-db,
|
|
e2e,
|
|
e2e-api-v2,
|
|
e2e-embed,
|
|
e2e-embed-react,
|
|
e2e-app-store,
|
|
]
|
|
if: always()
|
|
runs-on: buildjet-2vcpu-ubuntu-2204
|
|
steps:
|
|
- name: fail if conditional jobs failed
|
|
run: exit 1
|
|
if: |
|
|
(
|
|
needs.prepare.outputs.has-files-requiring-all-checks == 'true' &&
|
|
(
|
|
needs.lint.result != 'success' ||
|
|
needs.type-check.result != 'success' ||
|
|
needs.unit-test.result != 'success' ||
|
|
needs.build.result != 'success' ||
|
|
needs.build-api-v1.result != 'success' ||
|
|
needs.build-api-v2.result != 'success' ||
|
|
needs.build-atoms.result != 'success' ||
|
|
needs.build-docs.result != 'success' ||
|
|
needs.setup-db.result != 'success' ||
|
|
needs.integration-test.result != 'success' ||
|
|
needs.e2e.result != 'success' ||
|
|
needs.e2e-api-v2.result != 'success' ||
|
|
needs.e2e-embed.result != 'success' ||
|
|
needs.e2e-embed-react.result != 'success' ||
|
|
needs.e2e-app-store.result != 'success'
|
|
)
|
|
) ||
|
|
(
|
|
needs.prepare.outputs.has_companion == 'true' &&
|
|
needs.build-companion.result != 'success'
|
|
)
|