From e4833647946a0247b111078598c335b250360847 Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 15:25:28 +0100 Subject: [PATCH 1/7] ci: refactored and simplified ci/cd pipelines --- .github/README.md | 307 ++++++++++++++++++ .github/actions/build/action.yaml | 52 +-- .github/actions/changed-packages/action.yaml | 50 +++ .github/actions/deploy-docs/action.yaml | 52 +++ .github/actions/deploy-vercel/action.yaml | 54 +++ .github/actions/lint/action.yaml | 40 +++ .github/actions/preview/action.yaml | 48 --- .github/actions/quality/action.yaml | 16 - .github/actions/setup-env/action.yaml | 21 ++ .github/actions/test/action.yaml | 46 +++ .github/workflows/changed-packages.yaml | 44 --- .github/workflows/deploy-dev.yaml | 95 ------ .github/workflows/deploy-docs.yaml | 106 ++++++ .github/workflows/preview.yaml | 71 ---- .github/workflows/pull-request.yaml | 131 ++++++++ .github/workflows/release.yaml | 205 +++++------- .../mocked/src/modules/auth/auth.guard.ts | 1 - 17 files changed, 923 insertions(+), 416 deletions(-) create mode 100644 .github/README.md create mode 100644 .github/actions/changed-packages/action.yaml create mode 100644 .github/actions/deploy-docs/action.yaml create mode 100644 .github/actions/deploy-vercel/action.yaml create mode 100644 .github/actions/lint/action.yaml delete mode 100644 .github/actions/preview/action.yaml delete mode 100644 .github/actions/quality/action.yaml create mode 100644 .github/actions/test/action.yaml delete mode 100644 .github/workflows/changed-packages.yaml delete mode 100644 .github/workflows/deploy-dev.yaml create mode 100644 .github/workflows/deploy-docs.yaml delete mode 100644 .github/workflows/preview.yaml create mode 100644 .github/workflows/pull-request.yaml diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 000000000..15b21d2c6 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,307 @@ +# GitHub Actions CI/CD Documentation + +This directory contains GitHub Actions workflows and composite actions for the Open Self Service (O2S) project. + +## Workflow Diagrams + +### Pull Request Workflow +```mermaid +graph TD + A[PR Opened/Synchronized] --> B[skip-duplicate-check] + B -->|Skip if duplicate| C[changed-packages] + B -->|Skip if duplicate| D[build] + C --> E{docs package changed?} + D --> F[lint] + D --> G[test] + F --> H[deploy-docs-preview] + G --> H + E -->|Yes| H + E -->|No| I[End] + H --> J[Deploy to Vercel Preview] + + style B fill:#e1f5ff + style D fill:#fff4e1 + style F fill:#fff4e1 + style G fill:#fff4e1 + style H fill:#e8f5e9 +``` + +### Deploy Docs Workflow +```mermaid +graph TD + A[Tag: docs-v*.*.*] --> B[parse-docs-tag] + A --> C[build] + C --> D[lint] + C --> E[test] + B --> F[deploy-docs] + D --> F + E --> F + F --> G[Deploy to Vercel Production] + + style C fill:#fff4e1 + style D fill:#fff4e1 + style E fill:#fff4e1 + style F fill:#e8f5e9 +``` + +### Release Workflow +```mermaid +graph TD + A[Push to main] --> B[skip-duplicate-check] + B -->|Skip if duplicate| C[build] + B -->|Skip if duplicate| D[lint] + B -->|Skip if duplicate| E[test] + C --> D + C --> E + D --> F[publish-packages] + E --> F + F --> G{Packages to publish?} + G -->|Yes| H[Publish to npm] + G -->|No| I[Create Release PR] + + style B fill:#e1f5ff + style C fill:#fff4e1 + style D fill:#fff4e1 + style E fill:#fff4e1 + style F fill:#e8f5e9 +``` + +### Job Dependencies and Caching Flow +```mermaid +graph LR + A[setup-env] -->|Cache: node_modules| B[build] + A -->|Cache: node_modules| C[lint] + A -->|Cache: node_modules| D[test] + B -->|Cache: build outputs| C + B -->|Cache: build outputs| D + + style A fill:#e1f5ff + style B fill:#fff4e1 + style C fill:#fff4e1 + style D fill:#fff4e1 +``` + +## Workflows + +### `deploy-docs.yaml` +Deploys the docs app to Vercel production environment. + +**Trigger:** Push tag matching `docs-v*.*.*` pattern (e.g., `docs-v1.2.3`) + +**Jobs:** +- `parse-docs-tag`: Extracts version from tag +- `build`: Builds the project and caches build outputs (dist, build, .next directories, next-env.d.ts) +- `lint`: Lints the code - depends on `build` job and restores build outputs from cache +- `test`: Runs tests - depends on `build` job and restores build outputs from cache +- `deploy-docs`: Builds and deploys docs app to Vercel production (only runs after all quality checks pass) + +**Required Secrets:** +- `VERCEL_ACCESS_TOKEN`: Vercel API token +- `VERCEL_ORG_ID`: Vercel organization ID +- `VERCEL_DOCS_PROJECT_ID`: Vercel project ID for docs app + +### `release.yaml` +Publishes npm packages to the registry using Changesets. + +**Trigger:** Push to `main` branch + +**Jobs:** +- `skip-duplicate-check`: Prevents duplicate workflow runs +- `build`: Builds the project and caches build outputs (dist, build, .next directories, next-env.d.ts) +- `lint`: Lints the code - depends on `build` job and restores build outputs from cache +- `test`: Runs tests - depends on `build` job and restores build outputs from cache +- `publish-packages`: Publishes packages via Changesets (only runs after all quality checks pass) + +**Required Secrets:** +- `NPM_TOKEN`: npm authentication token +- `GITHUB_TOKEN`: GitHub token (automatically provided) +- `TURBO_TOKEN`: Turborepo token (optional, for remote caching) + +**Required Variables:** +- `TURBO_TEAM`: Turborepo team name (if using remote caching) + +### `pull-request.yaml` +Runs code quality checks (build, lint, test) on pull requests and optionally deploys docs preview. + +**Trigger:** Pull request events (`opened`, `synchronize`) + +**Jobs:** +- `skip-duplicate-check`: Prevents duplicate workflow runs +- `changed-packages`: Determines which packages changed (composite action) +- `build`: Builds the project and caches build outputs (dist, build, .next directories, next-env.d.ts) - always runs on PRs +- `lint`: Lints the code - depends on `build` job and restores build outputs from cache - always runs on PRs +- `test`: Runs tests - depends on `build` job and restores build outputs from cache - always runs on PRs +- `deploy-docs-preview`: Deploys docs preview to Vercel if docs package changed (only runs after all quality checks pass) + +**Required Secrets:** +- `VERCEL_ACCESS_TOKEN`: Vercel API token +- `VERCEL_ORG_ID`: Vercel organization ID +- `VERCEL_DOCS_PROJECT_ID`: Vercel project ID for docs app + +### `changed-packages` (Action) +Composite action that determines which packages have changed using Turborepo. + +**Inputs:** +- `event-name` (required): GitHub event name (`pull_request` or `push`) +- `base-sha` (optional): Base SHA for pull requests (default: empty) +- `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) + +**Outputs:** +- `package_changed`: JSON string containing changed packages information from turbo dry-run + +**Usage:** Used as a step in workflows to determine which packages changed + +## Composite Actions + +### `setup-env` +Sets up Node.js environment and installs dependencies with caching. + +**Inputs:** +- `repo-token` (required): GitHub token for repository access + +**Features:** +- Node.js 24 setup with npm caching via `actions/setup-node@v6` +- Caches `node_modules` and `generated` directories (cache key based on commit SHA) +- Only installs dependencies via `npm ci` if cache miss occurs +- Saves cache only if installation was performed + +### `build` +Runs the build process: checkout, setup environment, build project, and cache build outputs. + +**Inputs:** +- `repo-token` (required): GitHub token for repository access +- `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) + +**Steps:** +- Checks out code +- Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available +- Builds project: `npm run build` (Turborepo handles its own caching) +- Saves build outputs to cache: `dist`, `build`, `.next` directories, and `next-env.d.ts` (cache key based on commit SHA) + +### `lint` +Runs lint checks: checkout, setup environment, restore build outputs from cache, and lint. + +**Inputs:** +- `repo-token` (required): GitHub token for repository access +- `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) + +**Steps:** +- Checks out code +- Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available +- Restores build outputs from cache: `dist`, `build`, `.next` directories, and `next-env.d.ts` (cache key based on commit SHA) +- Lints code: `npm run lint` + +### `test` +Runs tests: checkout, setup environment, install Playwright browsers, restore build outputs from cache, and test. + +**Inputs:** +- `repo-token` (required): GitHub token for repository access +- `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) + +**Steps:** +- Checks out code +- Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available +- Restores build outputs from cache: `dist`, `build`, `.next` directories, and `next-env.d.ts` (cache key based on commit SHA) +- Installs Playwright browsers (required for Storybook tests) +- Runs tests: `npm run test` + + +### `changed-packages` +Determines which packages have changed using Turborepo. + +**Inputs:** +- `event-name` (required): GitHub event name (`pull_request` or `push`) +- `base-sha` (optional): Base SHA for pull requests (default: empty) +- `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) + +**Outputs:** +- `package_changed`: JSON string containing changed packages information from turbo dry-run + +**Steps:** +- Checks out code with full history +- Runs `turbo build --dry-run=json` to determine changed packages +- Outputs JSON result for use in workflow conditions + +### `deploy-vercel` +Unified action for deploying to Vercel (supports both production and preview environments). + +**Inputs:** +- `vercel-token` (required): Vercel API token +- `environment` (required): Vercel environment (`production` or `preview`) +- `build-args` (optional): Additional arguments for `vercel build` command (e.g., `--prod`) +- `deploy-args` (optional): Additional arguments for `vercel deploy` command (e.g., `--prod`) + +**Steps:** +- Installs Vercel CLI +- Pulls environment variables from Vercel (based on environment) +- Builds project locally +- Deploys prebuilt project to Vercel + +### `deploy-docs` +Complete workflow for deploying docs app: checkout, setup environment, and deploy to Vercel. + +**Inputs:** +- `repo-token` (required): GitHub token for repository access +- `vercel-token` (required): Vercel API token +- `vercel-project-id` (required): Vercel project ID for docs app +- `environment` (required): Vercel environment (`production` or `preview`) +- `fetch-depth` (optional): Git fetch depth for checkout (`0` for full history, `1` for shallow, default: `1`) +- `build-args` (optional): Additional arguments for Vercel build command +- `deploy-args` (optional): Additional arguments for Vercel deploy command + +**Steps:** +- Checks out code +- Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available +- Deploys to Vercel using `deploy-vercel` action + +**Note:** This action consolidates the common deployment workflow used by both production and preview deployments. Quality checks are run separately as dedicated jobs before deployment. + +## Best Practices + +### Caching +- **npm dependencies**: Cached via `actions/setup-node@v6` and explicit `actions/cache` for `node_modules` and `generated` directories + - Cache key: `{os}-install-{commit-sha}` + - Only installs if cache miss occurs +- **Build outputs**: Cached explicitly using `actions/cache` for `dist`, `build`, `.next` directories, and `next-env.d.ts` + - Cache key: `{os}-build-{commit-sha}` + - Restored by `lint` and `test` jobs +- **Turbo cache**: Handled automatically by Turborepo +- **Playwright browsers**: Cached by the Playwright installer + +### Concurrency +- All workflows use concurrency groups to prevent duplicate runs +- Production deployments (`deploy-docs.yaml`) use `cancel-in-progress: false` +- Preview and package publishing workflows use `cancel-in-progress: true` + +### Permissions +- All workflows follow the principle of least privilege +- Permissions are explicitly defined per workflow +- Only necessary permissions are granted + +### Error Handling +- Timeouts are set for long-running steps +- Quality checks must pass before deployments + +## Troubleshooting + +### Workflow not triggering +- Check that the trigger conditions are met (branch name, tag pattern, etc.) +- Verify that the workflow file is in `.github/workflows/` directory +- Check GitHub Actions tab for any error messages + +### Deployment failures +- Verify all required secrets are set in repository settings +- Check Vercel project configuration matches the project ID in secrets +- Review workflow logs for specific error messages + +### Package publishing issues +- Ensure Changesets are properly configured in the repository +- Verify `NPM_TOKEN` has publish permissions +- Check that package versions follow semantic versioning + +## Related Documentation + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Turborepo Documentation](https://turbo.build/repo/docs) +- [Changesets Documentation](https://github.com/changesets/changesets) +- [Vercel CLI Documentation](https://vercel.com/docs/cli) diff --git a/.github/actions/build/action.yaml b/.github/actions/build/action.yaml index f97167127..7d4d5a9b1 100644 --- a/.github/actions/build/action.yaml +++ b/.github/actions/build/action.yaml @@ -1,31 +1,41 @@ -name: Build package +name: Build + +description: 'Checkout code, setup environment, build project, and cache build outputs' inputs: - vercel-token: - description: 'Token to access the vercel' - required: true - pull-env-args: - description: 'Arguments to pull env from vercel' - required: true - build-env-args: - description: 'Arguments to build env' + repo-token: + description: 'Token to access the repository' required: true + fetch-depth: + description: 'Git fetch depth for checkout' + required: false + default: '0' runs: - using: "composite" + using: 'composite' steps: - - name: Install Vercel CLI - shell: bash - run: npm i --global vercel + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: ${{ inputs.fetch-depth }} - - name: Get Env - shell: bash - run: vercel pull ${{ inputs.pull-env-args }} --token=${{ inputs.vercel-token }} + - name: Prepare Environment + uses: ./.github/actions/setup-env + with: + repo-token: ${{ inputs.repo-token }} - - name: Vercel build local + - name: Build shell: bash - run: vercel build ${{ inputs.build-env-args }} + run: npm run build - - name: Deploy Prebuilt to Vercel - shell: bash - run: vercel deploy --prebuilt ${{ inputs.build-env-args }} --token=${{ inputs.vercel-token }} + - name: Save build outputs to cache + uses: actions/cache/save@v4 + if: always() + with: + path: | + **/dist/** + **/build/** + **/.next/** + **/next-env.d.ts + !**/node_modules/** + key: ${{ runner.os }}-build-${{ github.sha }} diff --git a/.github/actions/changed-packages/action.yaml b/.github/actions/changed-packages/action.yaml new file mode 100644 index 000000000..4b3b71ede --- /dev/null +++ b/.github/actions/changed-packages/action.yaml @@ -0,0 +1,50 @@ +name: Determine changed packages + +description: 'Determines which packages have changed using Turborepo. Returns JSON output with changed packages information.' + +inputs: + event-name: + description: 'GitHub event name (pull_request or push)' + required: true + base-sha: + description: 'Base SHA for pull requests (github.event.pull_request.base.sha)' + required: false + default: '' + fetch-depth: + description: 'Git fetch depth for checkout (0 for full history, required for turbo)' + required: false + default: '0' + +outputs: + package_changed: + description: 'JSON string containing changed packages information from turbo dry-run' + value: ${{ steps.changeset.outputs.result }} + +runs: + using: 'composite' + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + # We set fetch-depth to 0 so referenced commits are available for turbo + # This is required for turbo to detect changes properly + fetch-depth: ${{ inputs.fetch-depth }} + + - name: Determine changed packages + id: changeset + shell: bash + env: + # The turbo filter varies depending on if we're using this in a PR or on a push to a branch + # For PRs, we use github.event.pull_request.base.sha to see which packages changed since that SHA + # For branch pushes/merges, we reference HEAD^ to determine the previous HEAD + # See: https://stackoverflow.com/a/61861763/2379922 + TURBO_REF_FILTER: ${{ inputs.event-name == 'pull_request' && inputs.base-sha || 'HEAD^' }} + run: | + # 1. We need the 'output' of a turbo dry-run to get a json with all affected packages + # 2. The multi line json string is wrapped in EOF delimiters to make GHA happy + # See: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings + # 3. We specify the .github/ folder as a dependency. If workflows changed, we use that to mean + # everything has changes pending... to force redeploys + echo 'result<> $GITHUB_OUTPUT + echo "$(npx -y turbo build --dry-run=json --filter=...[$TURBO_REF_FILTER])" >> $GITHUB_OUTPUT + echo 'CHANGESET_DELIMITER' >> $GITHUB_OUTPUT diff --git a/.github/actions/deploy-docs/action.yaml b/.github/actions/deploy-docs/action.yaml new file mode 100644 index 000000000..ce0cc8fb2 --- /dev/null +++ b/.github/actions/deploy-docs/action.yaml @@ -0,0 +1,52 @@ +name: Deploy Docs + +description: 'Complete workflow for deploying docs app: checkout, setup environment, and deploy to Vercel' + +inputs: + repo-token: + description: 'Token to access the repository' + required: true + vercel-token: + description: 'Token to access Vercel' + required: true + vercel-project-id: + description: 'Vercel project ID for docs app' + required: true + environment: + description: 'Vercel environment (production or preview)' + required: true + fetch-depth: + description: 'Git fetch depth for checkout (0 for full history, 1 for shallow)' + required: false + default: '1' + build-args: + description: 'Additional arguments for Vercel build command' + required: false + default: '' + deploy-args: + description: 'Additional arguments for Vercel deploy command' + required: false + default: '' + +runs: + using: "composite" + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: ${{ inputs.fetch-depth }} + + - name: Prepare Environment + uses: ./.github/actions/setup-env + with: + repo-token: ${{ inputs.repo-token }} + + - name: Deploy to Vercel + env: + VERCEL_PROJECT_ID: ${{ inputs.vercel-project-id }} + uses: ./.github/actions/deploy-vercel + with: + vercel-token: ${{ inputs.vercel-token }} + environment: ${{ inputs.environment }} + build-args: ${{ inputs.build-args }} + deploy-args: ${{ inputs.deploy-args }} diff --git a/.github/actions/deploy-vercel/action.yaml b/.github/actions/deploy-vercel/action.yaml new file mode 100644 index 000000000..4c28be2d1 --- /dev/null +++ b/.github/actions/deploy-vercel/action.yaml @@ -0,0 +1,54 @@ +name: Deploy to Vercel + +description: 'Builds and deploys a project to Vercel (supports both production and preview environments)' + +inputs: + vercel-token: + description: 'Token to access Vercel' + required: true + environment: + description: 'Vercel environment (production or preview)' + required: true + default: 'preview' + build-args: + description: 'Additional arguments for Vercel build command (e.g., --prod for production)' + required: false + default: '' + deploy-args: + description: 'Additional arguments for Vercel deploy command (e.g., --prod for production)' + required: false + default: '' + +runs: + using: "composite" + steps: + - name: Install Vercel CLI + shell: bash + run: npm i --global vercel + + - name: Pull environment variables from Vercel + shell: bash + run: | + if [ "${{ inputs.environment }}" = "production" ]; then + vercel pull --environment=production --token=${{ inputs.vercel-token }} + else + vercel pull --environment=preview --token=${{ inputs.vercel-token }} + fi + + - name: Build project locally + shell: bash + run: | + if [ -n "${{ inputs.build-args }}" ]; then + vercel build ${{ inputs.build-args }} + else + vercel build + fi + + - name: Deploy prebuilt project to Vercel + shell: bash + run: | + if [ -n "${{ inputs.deploy-args }}" ]; then + vercel deploy --prebuilt ${{ inputs.deploy-args }} --token=${{ inputs.vercel-token }} + else + vercel deploy --prebuilt --token=${{ inputs.vercel-token }} + fi diff --git a/.github/actions/lint/action.yaml b/.github/actions/lint/action.yaml new file mode 100644 index 000000000..1441f477d --- /dev/null +++ b/.github/actions/lint/action.yaml @@ -0,0 +1,40 @@ +name: Lint + +description: 'Checkout code, setup environment, restore build outputs from cache, and run lint' + +inputs: + repo-token: + description: 'Token to access the repository' + required: true + fetch-depth: + description: 'Git fetch depth for checkout' + required: false + default: '0' + +runs: + using: 'composite' + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: ${{ inputs.fetch-depth }} + + - name: Prepare Environment + uses: ./.github/actions/setup-env + with: + repo-token: ${{ inputs.repo-token }} + + - name: Restore build outputs from cache + uses: actions/cache/restore@v4 + with: + path: | + **/dist/** + **/build/** + **/.next/** + **/next-env.d.ts + !**/node_modules/** + key: ${{ runner.os }}-build-${{ github.sha }} + + - name: Lint + shell: bash + run: npm run lint diff --git a/.github/actions/preview/action.yaml b/.github/actions/preview/action.yaml deleted file mode 100644 index c7d8255a4..000000000 --- a/.github/actions/preview/action.yaml +++ /dev/null @@ -1,48 +0,0 @@ -name: Build preview - -inputs: - vercel-token: - description: 'Token to access the vercel' - required: true - github-token: - description: 'Token to access the github' - required: true - vercel-org-id: - description: 'Vercel org id' - required: true - vercel-project-id: - description: 'Vercel project id to deploy' - required: true - vercel-project-name: - description: 'Vercel project name to deploy' - required: true - -runs: - using: "composite" - steps: - - name: Install Vercel CLI - shell: bash - run: npm i --global vercel - - - name: Get Env - shell: bash - run: vercel pull --environment=preview --token=${{ inputs.vercel-token }} - - - name: Vercel build local - shell: bash - run: vercel build - -# - name: Deploy -# uses: amondnet/vercel-action@v25 -# with: -# vercel-token: ${{ inputs.vercel-token}} # Required -# github-token: ${{ inputs.github-token }} #Optional -# vercel-args: "--prebuilt" -# vercel-org-id: ${{ inputs.vercel-org-id}} #Required -# vercel-project-id: ${{ inputs.vercel-project-id }} #Required -# vercel-project-name: ${{ inputs.vercel-project-name }} -# vercel-version: 30.2.0 - - - name: Deploy Prebuilt to Vercel - shell: bash - run: vercel deploy --prebuilt --token=${{ inputs.vercel-token }} diff --git a/.github/actions/quality/action.yaml b/.github/actions/quality/action.yaml deleted file mode 100644 index 4b0af31f5..000000000 --- a/.github/actions/quality/action.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Quality - -runs: - using: 'composite' - steps: - - name: Build - shell: bash - run: npm run build - - - name: Lint - shell: bash - run: npm run lint - - - name: Test - shell: bash - run: npm run test diff --git a/.github/actions/setup-env/action.yaml b/.github/actions/setup-env/action.yaml index b2987a661..dc268107f 100644 --- a/.github/actions/setup-env/action.yaml +++ b/.github/actions/setup-env/action.yaml @@ -1,5 +1,7 @@ name: Prepare environment +description: 'Sets up Node.js environment and installs dependencies with caching' + inputs: repo-token: description: 'Token to access the repo' @@ -13,8 +15,27 @@ runs: node-version: 24 cache: 'npm' + - name: Restore install outputs from cache + id: cache-install + uses: actions/cache/restore@v4 + with: + path: | + **/node_modules/** + **/generated/** + key: ${{ runner.os }}-install-${{ github.sha }} + - name: Install Packages + if: steps.cache-install.outputs.cache-hit != 'true' shell: bash run: npm ci env: CI: true + + - name: Save install output to cache + uses: actions/cache/save@v4 + if: steps.cache-install.outputs.cache-hit != 'true' + with: + path: | + **/node_modules/** + **/generated/** + key: ${{ runner.os }}-install-${{ github.sha }} diff --git a/.github/actions/test/action.yaml b/.github/actions/test/action.yaml new file mode 100644 index 000000000..c82b235b1 --- /dev/null +++ b/.github/actions/test/action.yaml @@ -0,0 +1,46 @@ +name: Test + +description: 'Checkout code, setup environment, install Playwright browsers, restore build outputs from cache, and run tests' + +inputs: + repo-token: + description: 'Token to access the repository' + required: true + fetch-depth: + description: 'Git fetch depth for checkout' + required: false + default: '0' + +runs: + using: 'composite' + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: ${{ inputs.fetch-depth }} + + - name: Prepare Environment + uses: ./.github/actions/setup-env + with: + repo-token: ${{ inputs.repo-token }} + + - name: Restore build outputs from cache + uses: actions/cache/restore@v4 + with: + path: | + **/dist/** + **/build/** + **/.next/** + **/next-env.d.ts + !**/node_modules/** + key: ${{ runner.os }}-build-${{ github.sha }} + + - name: Install Playwright Browsers + shell: bash + run: npx playwright install --with-deps + env: + CI: true + + - name: Test + shell: bash + run: npm run test diff --git a/.github/workflows/changed-packages.yaml b/.github/workflows/changed-packages.yaml deleted file mode 100644 index 257f1eaab..000000000 --- a/.github/workflows/changed-packages.yaml +++ /dev/null @@ -1,44 +0,0 @@ -name: 'Determine changed packages' - -on: - workflow_call: - outputs: - package_changed: - description: 'Dry run of turbo to determine which packages have changed since the last release' - value: ${{ jobs.dry-run.outputs.package_changed }} - -jobs: - dry-run: - runs-on: ubuntu-latest - env: - # The turbo filter here varies depending on if we're using this workflow in a PR or on a push to a branch - # For PRs, we want to use `github.event.pull_request.base.sha` to tell turbo to see which packages changed since that SHA - # For a branch push/merges, the above sha isn't available, so instead, we reference `github.event.before` to determine the previous `HEAD` of the branch we just pushed onto - # See SO answer for more info https://stackoverflow.com/a/61861763/2379922 - TURBO_REF_FILTER: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || 'HEAD^' }} - outputs: - # Defining a job output for used by the next jobs: - # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idoutputs - package_changed: ${{ steps.changeset.outputs.result }} - - steps: - - uses: actions/checkout@v6 - with: - # see `fetch-depth` in README: https://github.com/actions/checkout#checkout-v3, - # we set to `0` so the referenced commits are available for the command below - fetch-depth: 0 - - - name: Changeset - id: changeset - shell: bash - # 1. We need the 'output' of a turbo dry-run to get a json with all affected packages of these run. - # 2. The multi line json string is wrapped in EOF delimeters to make the GHA happy: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings - # 3. We specify the .github/ folder as a dependency here. Just to be safe, if workflows changed, we use that to mean everything has changes pending... to force redeploys - run: | - echo 'result<> $GITHUB_OUTPUT - echo "$(npx -y turbo build --dry-run=json --filter=...[$TURBO_REF_FILTER])" >> $GITHUB_OUTPUT - echo 'CHANGESET_DELIMITER' >> $GITHUB_OUTPUT -# - name: Echo info -# shell: bash -# run: | -# echo "Changeset: ${{ steps.changeset.outputs.result }}" diff --git a/.github/workflows/deploy-dev.yaml b/.github/workflows/deploy-dev.yaml deleted file mode 100644 index b122308c8..000000000 --- a/.github/workflows/deploy-dev.yaml +++ /dev/null @@ -1,95 +0,0 @@ -name: Release packages -permissions: - actions: write - contents: write - packages: write - checks: read - pull-requests: write - deployments: write - -env: - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ vars.TURBO_TEAM }} - -on: - push: - branches: - - main - -jobs: - pre_job: - runs-on: ubuntu-latest - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@v5 - with: - # All of these options are optional, so you can remove them if you are happy with the defaults - concurrent_skipping: 'outdated_runs' - # paths_ignore: '["**/README.md", ".github/**"]' - cancel_others: 'true' - - release-packages: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 2 - ref: ${{ needs.check-app.outputs.branch }} - - - name: Prepare Environment - uses: ./.github/actions/setup-env - timeout-minutes: 10 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Code Quality - uses: ./.github/actions/quality - timeout-minutes: 10 - - - name: Creating .npmrc - run: | - cat << EOF > "$HOME/.npmrc" - @o2s:registry=https://registry.npmjs.org - //registry.npmjs.org/:_authToken=$NPM_TOKEN - EOF - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Create Release Pull Request or Publish to npm - id: changesets - uses: changesets/action@v1 - with: - publish: npm run release - commit: 'feat(changeset): version packages' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} -# - name: Checkout code -# if: steps.changesets.outputs.published == 'true' -# uses: actions/checkout@v3 -# with: -# ref: create-o2s-app/base -# -# - name: Reset branch -# if: steps.changesets.outputs.published == 'true' -# run: | -# git fetch origin main:main -# git reset --hard main -# -# - name: Update api-harmonization dependencies -# if: steps.changesets.outputs.published == 'true' -# run: npm install @o2s/framework@latest @o2s/utils.logger@latest @o2s/integrations.mocked --workspace=@o2s/api-harmonization -# -# - name: Create create-o2s-app Pull Request -# id: cpr -# uses: peter-evans/create-pull-request@v7 -# if: steps.changesets.outputs.published == 'true' -# with: -# commit-message: 'feat(create-o2s-app): update dependencies' -# branch: create-o2s-app/patch -# delete-branch: true -# title: 'Update dependencies in create-o2s-app' diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml new file mode 100644 index 000000000..2afe25be2 --- /dev/null +++ b/.github/workflows/deploy-docs.yaml @@ -0,0 +1,106 @@ +name: Deploy Docs + +# Deploys the docs app to Vercel production when a docs-vX.X.X tag is pushed +# This workflow is triggered by tags matching the pattern docs-v*.*.* + +permissions: + actions: write + contents: read + deployments: write + +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} + +on: + push: + tags: + - 'docs-v*.*.*' + +concurrency: + group: deploy-docs-${{ github.ref }} + cancel-in-progress: false + +jobs: + parse-docs-tag: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.extract-version.outputs.version }} + steps: + - name: Extract version from tag + id: extract-version + run: | + # Extract version from docs-vX.X.X format (e.g., docs-v1.2.3 -> 1.2.3) + TAG="${GITHUB_REF#refs/tags/}" + VERSION="${TAG#docs-v}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Deploying docs version: $VERSION" + + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Build + uses: ./.github/actions/build + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + lint: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Lint + uses: ./.github/actions/lint + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + test: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Test + uses: ./.github/actions/test + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + deploy-docs: + runs-on: ubuntu-latest + needs: [parse-docs-tag, build, lint, test] + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Deploy Docs to Vercel Production + uses: ./.github/actions/deploy-docs + timeout-minutes: 20 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} + vercel-project-id: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} + environment: production + fetch-depth: '1' + build-args: '--prod' + deploy-args: '--prod' diff --git a/.github/workflows/preview.yaml b/.github/workflows/preview.yaml deleted file mode 100644 index dcf383211..000000000 --- a/.github/workflows/preview.yaml +++ /dev/null @@ -1,71 +0,0 @@ -name: Preview Deployment -permissions: - actions: write - contents: read - checks: read - pull-requests: write - deployments: write - -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - -on: - push: - branches: - - main - pull_request: - types: [opened, synchronize] - -jobs: - pre_job: - runs-on: ubuntu-latest - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@v5 - with: - # All of these options are optional, so you can remove them if you are happy with the defaults - concurrent_skipping: 'outdated_runs' - # paths_ignore: '["**/README.md", "**/ag-guideline.md", "**/docs/**", ".github/**"]' - cancel_others: 'true' - - changed-packages: - needs: pre_job - if: needs.pre_job.outputs.should_skip != 'true' - name: Determine which apps changed - uses: ./.github/workflows/changed-packages.yaml - - deploy-preview: - runs-on: ubuntu-latest - needs: [pre_job, changed-packages] - if: needs.pre_job.outputs.should_skip != 'true' - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 2 - ref: ${{ needs.check-app.outputs.branch }} - - - name: Prepare Environment - uses: ./.github/actions/setup-env - timeout-minutes: 10 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Code Quality - uses: ./.github/actions/quality - timeout-minutes: 10 - - - name: Deploy docs - if: contains(toJson(fromJson(needs.changed-packages.outputs.package_changed).packages), 'docs') && always() - env: - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} - uses: ./.github/actions/preview - timeout-minutes: 10 - with: - vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} # Required - github-token: ${{ secrets.GITHUB_TOKEN }} #Optional - vercel-org-id: ${{ secrets.VERCEL_ORG_ID}} #Required - vercel-project-id: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} #Required - vercel-project-name: 'docs' diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml new file mode 100644 index 000000000..04b48b8b6 --- /dev/null +++ b/.github/workflows/pull-request.yaml @@ -0,0 +1,131 @@ +name: PR Quality Checks and Preview + +# Runs code quality checks (build, lint, test) on pull requests +# Additionally deploys docs preview to Vercel if docs package changed + +permissions: + actions: write + contents: read + checks: read + pull-requests: write + deployments: write + +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + +on: + pull_request: + types: [opened, synchronize] + +concurrency: + group: pr-quality-checks-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + skip-duplicate-check: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 + with: + concurrent_skipping: 'outdated_runs' + cancel_others: 'true' + + changed-packages: + needs: skip-duplicate-check + if: needs.skip-duplicate-check.outputs.should_skip != 'true' + runs-on: ubuntu-latest + outputs: + package_changed: ${{ steps.determine-changes.outputs.package_changed }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Determine which packages changed + id: determine-changes + uses: ./.github/actions/changed-packages + with: + event-name: ${{ github.event_name }} + base-sha: ${{ github.event.pull_request.base.sha }} + fetch-depth: '0' + + build: + needs: skip-duplicate-check + if: needs.skip-duplicate-check.outputs.should_skip != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Build + uses: ./.github/actions/build + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + lint: + needs: [skip-duplicate-check, build] + if: needs.skip-duplicate-check.outputs.should_skip != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Lint + uses: ./.github/actions/lint + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + test: + needs: [skip-duplicate-check, build] + if: needs.skip-duplicate-check.outputs.should_skip != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Test + uses: ./.github/actions/test + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + deploy-docs-preview: + runs-on: ubuntu-latest + needs: [skip-duplicate-check, changed-packages, build, lint, test] + if: | + needs.skip-duplicate-check.outputs.should_skip != 'true' && + contains(toJson(fromJson(needs.changed-packages.outputs.package_changed).packages), 'docs') + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Deploy Docs Preview to Vercel + uses: ./.github/actions/deploy-docs + timeout-minutes: 20 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} + vercel-project-id: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} + environment: preview + fetch-depth: '0' + build-args: '' + deploy-args: '' diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 62a69b610..e9e4730a4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,155 +1,120 @@ name: Release + +# Publishes npm packages to the registry using Changesets +# This workflow runs on pushes to the main branch and handles versioning and publishing + permissions: - actions: write contents: write packages: write - checks: read pull-requests: write - deployments: write env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ vars.TURBO_TEAM }} + on: push: - tags: - - 'docs-v*.*.*' - - 'v*.*.*' + branches: + - main + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: true + jobs: - check-app: + skip-duplicate-check: runs-on: ubuntu-latest outputs: - app: ${{ steps.project-info.outputs.app }} - branch: ${{ steps.project-info.outputs.branch }} - pull_args: ${{ steps.project-info.outputs.pull_args }} + should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - - name: Extract Tag Info - id: tag-info-raw - uses: actions/github-script@v8 + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 with: - script: | - const tag = "${{ github.ref }}"; - const tripTag = tag.replace('refs/tags/', ''); - const regex = /^([a-z]+-)?v(\d+\.\d+(\.\d+)?)(-([a-z]+)(\.(\d+))?)?$/; - - const match = tripTag.match(regex); - - if (match) { - const prefix = match[1] ? match[1].slice(0, -1) : null; - const version = match[2]; - const suffix = match[5] ? match[5] : null; - const revision = match[7] ? match[7] : null; - - console.log(`Prefix: ${prefix}`); - console.log(`Version: ${version}`); - console.log(`Suffix: ${suffix}`); - console.log(`Revision: ${revision}`); - return { - app: prefix, - version: version, - branch: suffix, - revision: revision - } - } else { - console.log('Input string does not match expected format'); - return { - app: null, - version: null, - branch: null, - revision: null - }; - } - - - name: Extract tag to project info - id: project-info - run: | - VERCEL_PULL_ARGS="" - - APP=$(echo ${{ fromJson(steps.tag-info-raw.outputs.result).app }}) - BRANCH=$(echo ${{ fromJson(steps.tag-info-raw.outputs.result).branch }}) - ENV="" - - if [[ $BRANCH == "beta" ]]; then - BRANCH="staging" - VERCEL_PULL_ARGS="--environment=preview --git-branch=staging" - elif [[ $BRANCH == "alpha" ]]; then - BRANCH="testing" - VERCEL_PULL_ARGS="--environment=preview --git-branch=testing" - else - BRANCH="main" - VERCEL_PULL_ARGS="--environment=production" - fi - - if [[ -z "$APP" ]]; then - echo "App name is empty" - fi - - echo "app=$APP" >> $GITHUB_OUTPUT - echo "pull_args=$VERCEL_PULL_ARGS" >> $GITHUB_OUTPUT - echo "branch=$BRANCH" >> $GITHUB_OUTPUT - - create_release_single_app: + concurrent_skipping: 'outdated_runs' + cancel_others: 'true' + + build: + needs: skip-duplicate-check + if: needs.skip-duplicate-check.outputs.should_skip != 'true' runs-on: ubuntu-latest - needs: [check-app] - if: ${{ needs.check-app.outputs.app != null && needs.check-app.outputs.branch != null }} steps: - - name: Setup Vercel Project Id - run: | - APP=$(echo ${{ needs.check-app.outputs.app }}) - if [[ $APP == "docs" ]]; then - echo "Setting docs project id" - echo "VERCEL_PROJECT_ID=${{ secrets.VERCEL_DOCS_PROJECT_ID }}" >> $GITHUB_ENV - else - echo "App name is not valid" - # Exit to prevent further execution - exit 1 - fi - - name: Checkout code + - name: Checkout repository uses: actions/checkout@v6 with: - fetch-depth: 2 - ref: ${{ needs.check-app.outputs.branch }} - - name: Prepare Environment - uses: ./.github/actions/setup-env - timeout-minutes: 10 + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Build + uses: ./.github/actions/build with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Deploy Project to Vercel - uses: ./.github/actions/build - timeout-minutes: 10 + fetch-depth: '0' + + lint: + needs: [skip-duplicate-check, build] + if: needs.skip-duplicate-check.outputs.should_skip != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 with: - vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} - pull-env-args: ${{ needs.check-app.outputs.pull_args }} - build-env-args: ${{ needs.check-app.outputs.branch == 'main' && '--prod' || '' }} + # Minimal checkout just to make the action file available + fetch-depth: 1 - create_release_all_apps: + - name: Lint + uses: ./.github/actions/lint + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + test: + needs: [skip-duplicate-check, build] + if: needs.skip-duplicate-check.outputs.should_skip != 'true' runs-on: ubuntu-latest - needs: [check-app] - if: ${{ needs.check-app.outputs.app == null && needs.check-app.outputs.branch != null }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # Minimal checkout just to make the action file available + fetch-depth: 1 + + - name: Test + uses: ./.github/actions/test + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: '0' + + publish-packages: + runs-on: ubuntu-latest + needs: [skip-duplicate-check, build, lint, test] + if: needs.skip-duplicate-check.outputs.should_skip != 'true' steps: - name: Checkout code uses: actions/checkout@v6 with: - fetch-depth: 2 - ref: ${{ needs.check-app.outputs.branch }} + fetch-depth: 0 + - name: Prepare Environment uses: ./.github/actions/setup-env timeout-minutes: 10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Get Packages - id: app-packages - run: | - echo 'result<> $GITHUB_OUTPUT - echo "$(npx -y turbo build --dry-run=json --global-deps=.github/*)" >> $GITHUB_OUTPUT - echo 'CHANGESET_DELIMITER' >> $GITHUB_OUTPUT - - name: Deploy docs to Vercel - if: contains(toJson(fromJson(steps.app-packages.outputs.result).packages), 'docs') && always() + - name: Configure npm registry + run: | + cat << EOF > "$HOME/.npmrc" + @o2s:registry=https://registry.npmjs.org + //registry.npmjs.org/:_authToken=$NPM_TOKEN + EOF env: - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} - uses: ./.github/actions/build - timeout-minutes: 10 + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@v1 with: - vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} - pull-env-args: ${{ needs.check-app.outputs.pull_args }} - build-env-args: ${{ needs.check-app.outputs.branch == 'main' && '--prod' || '' }} + publish: npm run release + commit: 'feat(changeset): version packages' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/packages/integrations/mocked/src/modules/auth/auth.guard.ts b/packages/integrations/mocked/src/modules/auth/auth.guard.ts index b1cda4816..b6e709a72 100644 --- a/packages/integrations/mocked/src/modules/auth/auth.guard.ts +++ b/packages/integrations/mocked/src/modules/auth/auth.guard.ts @@ -1,6 +1,5 @@ import { ExecutionContext, Inject, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; -import jwt from 'jsonwebtoken'; import { LoggerService } from '@o2s/utils.logger'; From c01930c08a937609937bc7f1e8e4cf76a48edce3 Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 15:26:17 +0100 Subject: [PATCH 2/7] ci: refactored and simplified ci/cd pipelines --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index f7c213fa8..581f8c371 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "o2s", "private": true, "scripts": { - "postinstall": "npx playwright install --with-deps chromium", "prepare": "husky", "dev": "turbo watch dev", "predev": "turbo build -F=!{./apps/*} -F=!{./packages/cli/*}", From 9507ad98a259eeaf4a7bf4cbd3108f4b58460db6 Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 15:38:51 +0100 Subject: [PATCH 3/7] ci: refactored and simplified ci/cd pipelines --- .github/README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/README.md b/.github/README.md index 15b21d2c6..7827f2960 100644 --- a/.github/README.md +++ b/.github/README.md @@ -8,8 +8,8 @@ This directory contains GitHub Actions workflows and composite actions for the O ```mermaid graph TD A[PR Opened/Synchronized] --> B[skip-duplicate-check] - B -->|Skip if duplicate| C[changed-packages] - B -->|Skip if duplicate| D[build] + B --> C[changed-packages] + B --> D[build] C --> E{docs package changed?} D --> F[lint] D --> G[test] @@ -48,11 +48,9 @@ graph TD ```mermaid graph TD A[Push to main] --> B[skip-duplicate-check] - B -->|Skip if duplicate| C[build] - B -->|Skip if duplicate| D[lint] - B -->|Skip if duplicate| E[test] - C --> D - C --> E + B --> C[build] + C --> D[lint] + C --> E[test] D --> F[publish-packages] E --> F F --> G{Packages to publish?} From 8bfcb69487b99ffeb2c0e2c67fdab25d43392331 Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 15:39:31 +0100 Subject: [PATCH 4/7] ci: refactored and simplified ci/cd pipelines --- .../mocked/src/modules/auth/auth.guard.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/integrations/mocked/src/modules/auth/auth.guard.ts b/packages/integrations/mocked/src/modules/auth/auth.guard.ts index b6e709a72..fea272678 100644 --- a/packages/integrations/mocked/src/modules/auth/auth.guard.ts +++ b/packages/integrations/mocked/src/modules/auth/auth.guard.ts @@ -1,12 +1,33 @@ import { ExecutionContext, Inject, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; +import jwt from 'jsonwebtoken'; + + import { LoggerService } from '@o2s/utils.logger'; + + import { Auth } from '@o2s/framework/modules'; + + import { Jwt } from './auth.model'; + + + + + + + + + + + + + + @Injectable() export class RolesGuard implements Auth.Guard { constructor( From 1008e81824918690d1506aa06394df3e1221da97 Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 15:39:41 +0100 Subject: [PATCH 5/7] ci: refactored and simplified ci/cd pipelines --- .../mocked/src/modules/auth/auth.guard.ts | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/packages/integrations/mocked/src/modules/auth/auth.guard.ts b/packages/integrations/mocked/src/modules/auth/auth.guard.ts index fea272678..b1cda4816 100644 --- a/packages/integrations/mocked/src/modules/auth/auth.guard.ts +++ b/packages/integrations/mocked/src/modules/auth/auth.guard.ts @@ -2,32 +2,12 @@ import { ExecutionContext, Inject, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import jwt from 'jsonwebtoken'; - - import { LoggerService } from '@o2s/utils.logger'; - - import { Auth } from '@o2s/framework/modules'; - - import { Jwt } from './auth.model'; - - - - - - - - - - - - - - @Injectable() export class RolesGuard implements Auth.Guard { constructor( From ed7b130c84c9353d88ce49e5938e807c45a8d4bd Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 15:49:37 +0100 Subject: [PATCH 6/7] ci: refactored and simplified ci/cd pipelines --- .github/actions/build/action.yaml | 2 +- .github/actions/deploy-docs/action.yaml | 6 ++++++ .github/actions/deploy-vercel/action.yaml | 9 +++++++++ .github/workflows/deploy-docs.yaml | 1 + .github/workflows/pull-request.yaml | 1 + 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/actions/build/action.yaml b/.github/actions/build/action.yaml index 7d4d5a9b1..05e6e12e4 100644 --- a/.github/actions/build/action.yaml +++ b/.github/actions/build/action.yaml @@ -30,7 +30,7 @@ runs: - name: Save build outputs to cache uses: actions/cache/save@v4 - if: always() + if: success() with: path: | **/dist/** diff --git a/.github/actions/deploy-docs/action.yaml b/.github/actions/deploy-docs/action.yaml index ce0cc8fb2..9192a59c9 100644 --- a/.github/actions/deploy-docs/action.yaml +++ b/.github/actions/deploy-docs/action.yaml @@ -9,6 +9,9 @@ inputs: vercel-token: description: 'Token to access Vercel' required: true + vercel-org-id: + description: 'Vercel Organization ID' + required: true vercel-project-id: description: 'Vercel project ID for docs app' required: true @@ -43,10 +46,13 @@ runs: - name: Deploy to Vercel env: + VERCEL_ORG_ID: ${{ inputs.vercel-org-id }} VERCEL_PROJECT_ID: ${{ inputs.vercel-project-id }} uses: ./.github/actions/deploy-vercel with: vercel-token: ${{ inputs.vercel-token }} + vercel-org-id: ${{ inputs.vercel-org-id }} + vercel-project-id: ${{ inputs.vercel-project-id }} environment: ${{ inputs.environment }} build-args: ${{ inputs.build-args }} deploy-args: ${{ inputs.deploy-args }} diff --git a/.github/actions/deploy-vercel/action.yaml b/.github/actions/deploy-vercel/action.yaml index 4c28be2d1..6655c7c03 100644 --- a/.github/actions/deploy-vercel/action.yaml +++ b/.github/actions/deploy-vercel/action.yaml @@ -6,6 +6,12 @@ inputs: vercel-token: description: 'Token to access Vercel' required: true + vercel-org-id: + description: 'Vercel Organization ID' + required: true + vercel-project-id: + description: 'Vercel Project ID' + required: true environment: description: 'Vercel environment (production or preview)' required: true @@ -28,6 +34,9 @@ runs: - name: Pull environment variables from Vercel shell: bash + env: + VERCEL_ORG_ID: ${{ inputs.vercel-org-id }} + VERCEL_PROJECT_ID: ${{ inputs.vercel-project-id }} run: | if [ "${{ inputs.environment }}" = "production" ]; then vercel pull --environment=production --token=${{ inputs.vercel-token }} diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml index 2afe25be2..e6f85c7f6 100644 --- a/.github/workflows/deploy-docs.yaml +++ b/.github/workflows/deploy-docs.yaml @@ -99,6 +99,7 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} + vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} environment: production fetch-depth: '1' diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml index 04b48b8b6..d693f17df 100644 --- a/.github/workflows/pull-request.yaml +++ b/.github/workflows/pull-request.yaml @@ -124,6 +124,7 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} vercel-token: ${{ secrets.VERCEL_ACCESS_TOKEN }} + vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} environment: preview fetch-depth: '0' From 1afdc762c779dec9d180f63f25a4622b27b3944a Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Wed, 21 Jan 2026 16:17:47 +0100 Subject: [PATCH 7/7] ci: refactored and simplified ci/cd pipelines --- .github/README.md | 65 ++++++++++++++++------- .github/actions/deploy-vercel/action.yaml | 6 ++- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/.github/README.md b/.github/README.md index 7827f2960..3bc8a9742 100644 --- a/.github/README.md +++ b/.github/README.md @@ -5,6 +5,7 @@ This directory contains GitHub Actions workflows and composite actions for the O ## Workflow Diagrams ### Pull Request Workflow + ```mermaid graph TD A[PR Opened/Synchronized] --> B[skip-duplicate-check] @@ -27,6 +28,7 @@ graph TD ``` ### Deploy Docs Workflow + ```mermaid graph TD A[Tag: docs-v*.*.*] --> B[parse-docs-tag] @@ -45,6 +47,7 @@ graph TD ``` ### Release Workflow + ```mermaid graph TD A[Push to main] --> B[skip-duplicate-check] @@ -65,6 +68,7 @@ graph TD ``` ### Job Dependencies and Caching Flow + ```mermaid graph LR A[setup-env] -->|Cache: node_modules| B[build] @@ -82,11 +86,13 @@ graph LR ## Workflows ### `deploy-docs.yaml` + Deploys the docs app to Vercel production environment. **Trigger:** Push tag matching `docs-v*.*.*` pattern (e.g., `docs-v1.2.3`) **Jobs:** + - `parse-docs-tag`: Extracts version from tag - `build`: Builds the project and caches build outputs (dist, build, .next directories, next-env.d.ts) - `lint`: Lints the code - depends on `build` job and restores build outputs from cache @@ -94,16 +100,19 @@ Deploys the docs app to Vercel production environment. - `deploy-docs`: Builds and deploys docs app to Vercel production (only runs after all quality checks pass) **Required Secrets:** + - `VERCEL_ACCESS_TOKEN`: Vercel API token - `VERCEL_ORG_ID`: Vercel organization ID - `VERCEL_DOCS_PROJECT_ID`: Vercel project ID for docs app ### `release.yaml` + Publishes npm packages to the registry using Changesets. **Trigger:** Push to `main` branch **Jobs:** + - `skip-duplicate-check`: Prevents duplicate workflow runs - `build`: Builds the project and caches build outputs (dist, build, .next directories, next-env.d.ts) - `lint`: Lints the code - depends on `build` job and restores build outputs from cache @@ -111,19 +120,23 @@ Publishes npm packages to the registry using Changesets. - `publish-packages`: Publishes packages via Changesets (only runs after all quality checks pass) **Required Secrets:** + - `NPM_TOKEN`: npm authentication token - `GITHUB_TOKEN`: GitHub token (automatically provided) - `TURBO_TOKEN`: Turborepo token (optional, for remote caching) **Required Variables:** + - `TURBO_TEAM`: Turborepo team name (if using remote caching) ### `pull-request.yaml` + Runs code quality checks (build, lint, test) on pull requests and optionally deploys docs preview. **Trigger:** Pull request events (`opened`, `synchronize`) **Jobs:** + - `skip-duplicate-check`: Prevents duplicate workflow runs - `changed-packages`: Determines which packages changed (composite action) - `build`: Builds the project and caches build outputs (dist, build, .next directories, next-env.d.ts) - always runs on PRs @@ -132,113 +145,121 @@ Runs code quality checks (build, lint, test) on pull requests and optionally dep - `deploy-docs-preview`: Deploys docs preview to Vercel if docs package changed (only runs after all quality checks pass) **Required Secrets:** + - `VERCEL_ACCESS_TOKEN`: Vercel API token - `VERCEL_ORG_ID`: Vercel organization ID - `VERCEL_DOCS_PROJECT_ID`: Vercel project ID for docs app -### `changed-packages` (Action) -Composite action that determines which packages have changed using Turborepo. - -**Inputs:** -- `event-name` (required): GitHub event name (`pull_request` or `push`) -- `base-sha` (optional): Base SHA for pull requests (default: empty) -- `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) - -**Outputs:** -- `package_changed`: JSON string containing changed packages information from turbo dry-run - -**Usage:** Used as a step in workflows to determine which packages changed - ## Composite Actions ### `setup-env` + Sets up Node.js environment and installs dependencies with caching. **Inputs:** + - `repo-token` (required): GitHub token for repository access **Features:** + - Node.js 24 setup with npm caching via `actions/setup-node@v6` - Caches `node_modules` and `generated` directories (cache key based on commit SHA) - Only installs dependencies via `npm ci` if cache miss occurs - Saves cache only if installation was performed ### `build` + Runs the build process: checkout, setup environment, build project, and cache build outputs. **Inputs:** + - `repo-token` (required): GitHub token for repository access - `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) **Steps:** + - Checks out code - Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available - Builds project: `npm run build` (Turborepo handles its own caching) - Saves build outputs to cache: `dist`, `build`, `.next` directories, and `next-env.d.ts` (cache key based on commit SHA) ### `lint` + Runs lint checks: checkout, setup environment, restore build outputs from cache, and lint. **Inputs:** + - `repo-token` (required): GitHub token for repository access - `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) **Steps:** + - Checks out code - Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available - Restores build outputs from cache: `dist`, `build`, `.next` directories, and `next-env.d.ts` (cache key based on commit SHA) - Lints code: `npm run lint` ### `test` + Runs tests: checkout, setup environment, install Playwright browsers, restore build outputs from cache, and test. **Inputs:** + - `repo-token` (required): GitHub token for repository access - `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) **Steps:** + - Checks out code - Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available - Restores build outputs from cache: `dist`, `build`, `.next` directories, and `next-env.d.ts` (cache key based on commit SHA) - Installs Playwright browsers (required for Storybook tests) - Runs tests: `npm run test` - ### `changed-packages` + Determines which packages have changed using Turborepo. **Inputs:** + - `event-name` (required): GitHub event name (`pull_request` or `push`) - `base-sha` (optional): Base SHA for pull requests (default: empty) - `fetch-depth` (optional): Git fetch depth for checkout (default: `0`) **Outputs:** + - `package_changed`: JSON string containing changed packages information from turbo dry-run **Steps:** + - Checks out code with full history - Runs `turbo build --dry-run=json` to determine changed packages - Outputs JSON result for use in workflow conditions ### `deploy-vercel` + Unified action for deploying to Vercel (supports both production and preview environments). **Inputs:** + - `vercel-token` (required): Vercel API token - `environment` (required): Vercel environment (`production` or `preview`) - `build-args` (optional): Additional arguments for `vercel build` command (e.g., `--prod`) - `deploy-args` (optional): Additional arguments for `vercel deploy` command (e.g., `--prod`) **Steps:** + - Installs Vercel CLI - Pulls environment variables from Vercel (based on environment) - Builds project locally - Deploys prebuilt project to Vercel ### `deploy-docs` + Complete workflow for deploying docs app: checkout, setup environment, and deploy to Vercel. **Inputs:** + - `repo-token` (required): GitHub token for repository access - `vercel-token` (required): Vercel API token - `vercel-project-id` (required): Vercel project ID for docs app @@ -248,6 +269,7 @@ Complete workflow for deploying docs app: checkout, setup environment, and deplo - `deploy-args` (optional): Additional arguments for Vercel deploy command **Steps:** + - Checks out code - Prepares environment (Node.js, dependencies) - restores `node_modules` from cache if available - Deploys to Vercel using `deploy-vercel` action @@ -257,42 +279,49 @@ Complete workflow for deploying docs app: checkout, setup environment, and deplo ## Best Practices ### Caching + - **npm dependencies**: Cached via `actions/setup-node@v6` and explicit `actions/cache` for `node_modules` and `generated` directories - - Cache key: `{os}-install-{commit-sha}` - - Only installs if cache miss occurs + - Cache key: `{os}-install-{commit-sha}` + - Only installs if cache miss occurs - **Build outputs**: Cached explicitly using `actions/cache` for `dist`, `build`, `.next` directories, and `next-env.d.ts` - - Cache key: `{os}-build-{commit-sha}` - - Restored by `lint` and `test` jobs + - Cache key: `{os}-build-{commit-sha}` + - Restored by `lint` and `test` jobs - **Turbo cache**: Handled automatically by Turborepo - **Playwright browsers**: Cached by the Playwright installer ### Concurrency + - All workflows use concurrency groups to prevent duplicate runs - Production deployments (`deploy-docs.yaml`) use `cancel-in-progress: false` - Preview and package publishing workflows use `cancel-in-progress: true` ### Permissions + - All workflows follow the principle of least privilege - Permissions are explicitly defined per workflow - Only necessary permissions are granted ### Error Handling + - Timeouts are set for long-running steps - Quality checks must pass before deployments ## Troubleshooting ### Workflow not triggering + - Check that the trigger conditions are met (branch name, tag pattern, etc.) - Verify that the workflow file is in `.github/workflows/` directory - Check GitHub Actions tab for any error messages ### Deployment failures + - Verify all required secrets are set in repository settings - Check Vercel project configuration matches the project ID in secrets - Review workflow logs for specific error messages ### Package publishing issues + - Ensure Changesets are properly configured in the repository - Verify `NPM_TOKEN` has publish permissions - Check that package versions follow semantic versioning diff --git a/.github/actions/deploy-vercel/action.yaml b/.github/actions/deploy-vercel/action.yaml index 6655c7c03..0b5fea562 100644 --- a/.github/actions/deploy-vercel/action.yaml +++ b/.github/actions/deploy-vercel/action.yaml @@ -46,9 +46,11 @@ runs: - name: Build project locally shell: bash + env: + BUILD_ARGS: ${{ inputs.build-args }} run: | - if [ -n "${{ inputs.build-args }}" ]; then - vercel build ${{ inputs.build-args }} + if [ -n "$BUILD_ARGS" ]; then + vercel build $BUILD_ARGS else vercel build fi