From 288d75221386df7379a77fdbe2ca81d7faa7dbe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Thu, 20 Feb 2025 17:18:10 +0700 Subject: [PATCH 1/7] docs(TF-410): ci/cd draft --- .../4.deployment/8.ci-cd.md | 236 +++++++++++++++++- 1 file changed, 233 insertions(+), 3 deletions(-) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md index c7f538d4e4..052c8c4e18 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md @@ -7,14 +7,244 @@ navigation: # Deployment - CI/CD +Ever wondered how to efficiently deploy multiple stores in a production environment? This guide explains how Continuous Integration (CI) and Continuous Deployment (CD) work in a multistore setup, making your deployment process smooth and reliable. -::card{title="Next: CLI Reference" icon="tabler:number-3-small" } +**What You'll Learn** + +::list{type="success"} +- Understanding CI/CD in a multistore context +- How to implement change detection for stores +- How to set up parallel store deployments +- Best practices for any CI/CD platform +:: + +## Core Concepts + +### What is CI/CD in Multistore? + +In a multistore setup, CI/CD is designed to: +1. Automatically detect which stores have changed +2. Run tests only for affected stores +3. Deploy only the necessary stores to production + +This targeted approach ensures: +- Faster deployments (only changed stores are processed) +- Efficient resource usage +- Reduced risk (unchanged stores remain untouched) + +## Implementation Steps + +Let's break down how to implement CI/CD for multiple stores, using GitHub Actions as an example while explaining how to adapt each step for other CI platforms. + +### 1. Setting Up Dependencies + +First, you need to set up your environment with the necessary dependencies: + +```yaml +steps: + # 1. Check out your code + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Important: Need full history for change detection + + # 2. Set up Node.js + - name: Install dependencies + run: | + npm install + # Configure private registry if needed + npm config set @your-scope:registry https://your-registry.com +``` + +::tip{title="Adapting for Other CI Platforms"} +Key requirements for any CI platform: +- Full git history access (for change detection) +- Node.js environment +- Access to your npm registry +- Environment variables for credentials +:: + +### 2. Change Detection + +The change detection step identifies which stores need deployment: + +```yaml +steps: + - name: Find affected stores + id: affectedStores + run: | + # Get list of changed stores + STORE_IDS=$(yarn store changed --since ${{ github.event.pull_request.base.sha }} --condensed) + + # Format for CI platform + echo "storeIds=$STORE_IDS" >> $GITHUB_OUTPUT + + # Create flag format for CLI + if [ "$STORE_IDS" != "[]" ]; then + STORE_FLAGS=$(echo $STORE_IDS | jq -r 'map("--store-id " + .) | join(" ")') + echo "storeIdsFlag=$STORE_FLAGS" >> $GITHUB_OUTPUT + fi +``` + +::tip{title="Implementing in Other CI Systems"} +To implement change detection: +1. Run `yarn store changed --since ` +2. Parse the JSON output into your CI platform's variable format +3. Use these variables to control subsequent steps +:: + +### 3. Running Tests + +Once you know which stores changed, run tests only for those stores: + +```yaml +steps: + - name: Run integration tests + if: ${{ steps.affectedStores.outputs.storeIds != '[]' }} + run: | + # Install test dependencies + yarn playwright install --with-deps chromium + + # Run tests for affected stores + yarn store test ${{ steps.affectedStores.outputs.storeIdsFlag }} +``` + +::tip{title="Cross-Platform Testing"} +Key considerations for any CI platform: +1. Install test dependencies +2. Use the store IDs from change detection +3. Set appropriate timeouts +4. Configure test result reporting +:: + +### 4. Building Stores + +Before deployment, build the affected stores: +```yaml +steps: + - name: Build affected stores + if: ${{ steps.affectedStores.outputs.storeIds != '[]' }} + run: | + yarn store build ${{ steps.affectedStores.outputs.storeIdsFlag }} +``` + +### 5. Parallel Deployment + +The final step is deploying the stores in parallel. Here's how to structure this in different CI systems: + +::code-group +```yaml [GitHub Actions] +jobs: + deploy: + name: Deploy ${{ matrix.store_id }} store + strategy: + matrix: + store_id: ${{ fromJson(needs.chooseStoresToDeploy.outputs.storeIds) }} + steps: + - name: Deploy store + run: yarn store deploy --store-id ${{ matrix.store_id }} +``` + +```yaml [GitLab CI] +deploy: + parallel: + matrix: + - STORE_ID: $STORE_IDS # Define this variable in previous stage + script: + - yarn store deploy --store-id $STORE_ID +``` + +```yaml [Jenkins Pipeline] +stage('Deploy') { + steps { + script { + def storeIds = readJSON(text: STORE_IDS) + parallel storeIds.collectEntries { storeId -> + ["${storeId}" : { + sh "yarn store deploy --store-id ${storeId}" + }] + } + } + } +} +``` +:: + +::tip{title="Implementing Parallel Deployments"} +Key requirements for any CI platform: +1. Support for parallel job execution +2. Ability to share variables between jobs +3. Individual job retry capabilities +4. Proper error handling and reporting +:: + +## Version Control + +### CLI Version Management + +It's crucial to use a fixed CLI version across all environments: + +```yaml +steps: + - name: Get CLI version + id: cli_version + run: | + CLI_VERSION=$(jq -r '.dependencies["@alokai/cli"]' package.json) + echo "Using CLI version: $CLI_VERSION" + echo "CLI_VERSION=$CLI_VERSION" >> $GITHUB_OUTPUT + + - name: Deploy with specific version + run: npx @alokai/cli@${{ steps.cli_version.outputs.CLI_VERSION }} store deploy +``` + +::warning{title="Version Consistency"} +Ensure the same CLI version is used in: +- Local development +- CI/CD pipelines +- Production deployments +:: + +## Best Practices + +1. **Environment Setup** + - Use dependency caching + - Set up proper timeout values + - Configure error reporting + +2. **Change Detection** + - Configure global dependencies properly + - Use appropriate git depth + - Handle branch merges correctly + +3. **Deployment Strategy** + - Implement proper rollback procedures + - Set up deployment verification + - Configure proper logging + +## Common Pitfalls + +1. **Git Configuration** + - Insufficient git history depth + - Missing branch information + - Incorrect merge base detection + +2. **Resource Management** + - Excessive parallel jobs + - Missing timeout configurations + - Insufficient cleanup procedures + +3. **Error Handling** + - Missing failure notifications + - Incomplete error logs + - Poor retry mechanisms + +::card{title="Next: CLI Reference" icon="tabler:number-3-small" } #description -TODO +Learn more about the CLI commands used in CI/CD pipelines. #cta :::docs-arrow-link{to="/guides/multistore/tooling-and-concepts/cli-reference"} Next ::: -:: +:: \ No newline at end of file From a35ad2b1a0310f19ac230cb2f05d001fb58d9a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Thu, 20 Feb 2025 21:27:11 +0700 Subject: [PATCH 2/7] docs: complete docs --- .../4.deployment/8.ci-cd.md | 455 ++++++++++++------ 1 file changed, 309 insertions(+), 146 deletions(-) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md index 052c8c4e18..272345f853 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md @@ -7,15 +7,15 @@ navigation: # Deployment - CI/CD -Ever wondered how to efficiently deploy multiple stores in a production environment? This guide explains how Continuous Integration (CI) and Continuous Deployment (CD) work in a multistore setup, making your deployment process smooth and reliable. +Managing deployments for multiple stores can be challenging. This guide explains how Continuous Integration (CI) and Continuous Deployment (CD) work in a multistore setup, helping you create an efficient and reliable deployment process. **What You'll Learn** ::list{type="success"} -- Understanding CI/CD in a multistore context -- How to implement change detection for stores -- How to set up parallel store deployments -- Best practices for any CI/CD platform +- How to set up CI/CD pipeline using GitHub Actions +- How to detect and process only changed stores +- How to efficiently deploy multiple stores in parallel +- Advanced topics like change detection mechanism and CLI-driven approach :: ## Core Concepts @@ -25,20 +25,84 @@ Ever wondered how to efficiently deploy multiple stores in a production environm In a multistore setup, CI/CD is designed to: 1. Automatically detect which stores have changed 2. Run tests only for affected stores -3. Deploy only the necessary stores to production +3. Build and deploy only the changed stores This targeted approach ensures: - Faster deployments (only changed stores are processed) - Efficient resource usage -- Reduced risk (unchanged stores remain untouched) +- Reduced redundancy (unchanged stores are skipped in CI/CD pipeline) -## Implementation Steps +## Continuous Integration (CI) -Let's break down how to implement CI/CD for multiple stores, using GitHub Actions as an example while explaining how to adapt each step for other CI platforms. +Let's look at how continuous integration works in a multistore setup, using GitHub Actions as an example while explaining how to adapt each step for other CI platforms. ### 1. Setting Up Dependencies -First, you need to set up your environment with the necessary dependencies: +First, we need to set up the environment. Our setup action handles several crucial steps: + +::tip Why a Separate Setup Action? +We use a separate setup action to follow the DRY (Don't Repeat Yourself) principle, as these setup steps are used in multiple workflows - for instance `continuous-integration.yml` and `continuous-deployment.yml`. However, you can include these steps directly in your workflow if you prefer - there's no technical requirement to have them as a separate action. +:: + +Here's how our setup action is defined: + +```yaml +name: Setup repository +description: Installs all the packages and initializes environment variables + +# Define required inputs for npm registry authentication +inputs: + npm_user: + description: Enterprise NPM registry user + required: true + npm_password: + description: Enterprise NPM registry password + required: true + npm_email: + description: Enterprise NPM registry email + required: true + +runs: + using: composite + steps: + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version-file: ./.nvmrc + + # Configure Yarn cache to speed up installations + - name: Yarn cache + uses: actions/cache@v4 + with: + path: .yarn + key: storefront-yarn-cache + + # Set up Turbo cache for faster builds + - name: Cache turbo build setup + uses: actions/cache@v4 + with: + path: .turbo + key: starter-turbo-${{ github.sha }} + restore-keys: | + starter-turbo- + + # Configure access to private npm registry + - name: Configure NPM registry + shell: bash + run: | + npm install -g npm-cli-login; + npm-cli-login -u ${{ inputs.npm_user }} -p ${{ inputs.npm_password }} -e ${{ inputs.npm_email }} -r https://registrynpm.storefrontcloud.io || exit 1; + + # Install all project dependencies + - name: Install dependencies + shell: bash + # We use frozen-lockfile to ensure consistent dependencies across all environments + # This is important for CI/CD to avoid unexpected issues + # We run init.mjs to ensure the project is properly initialized + run: yarn install --frozen-lockfile --cache-folder .yarn && node init.mjs +``` + +And here's how we use it in our workflow: ```yaml steps: @@ -46,198 +110,297 @@ steps: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Important: Need full history for change detection + fetch-depth: 0 # Important: Need full git history for change detection - # 2. Set up Node.js + # 2. Set up environment using our custom action - name: Install dependencies - run: | - npm install - # Configure private registry if needed - npm config set @your-scope:registry https://your-registry.com + uses: ./.github/actions/setup + with: + npm_user: ${{ vars.NPM_USER }} + npm_password: ${{ secrets.NPM_PASS }} + npm_email: ${{ vars.NPM_EMAIL }} ``` -::tip{title="Adapting for Other CI Platforms"} -Key requirements for any CI platform: -- Full git history access (for change detection) -- Node.js environment -- Access to your npm registry -- Environment variables for credentials +::tip Adapting for Other CI Platforms +Your CI platform needs to support: full git history access for change detection, Node.js environment setup, Yarn cache configuration, Turbo build cache setup for faster builds, and access to Alokai Enterprise Registry. :: ### 2. Change Detection -The change detection step identifies which stores need deployment: +The change detection step identifies which stores need deployment. Here's a simplified version of our approach: + +::tip +While we recommend using change detection for efficiency, you can skip it and run actions for all stores using the `--all` flag: +```bash +# Run tests for all stores regardless of changes +yarn store test --all + +# Deploy all stores +yarn store deploy --all +``` +:: + +```yaml +name: Affected Stores +description: Determines which stores are affected + +inputs: + since: + description: Base commit for changes + required: false + to: + description: Head commit for changes + required: false + +runs: + using: composite + steps: + - name: Find affected stores + run: | + # Basic change detection + # Determine affected stores using the storefront CLI + yarn store changed --condensed --since ${{ inputs.since }} --to ${{ inputs.to }} > changed_stores.json + + # Extract store IDs from the output + STORES=$(jq -r '. | join(" ")' changed_stores.json) + + # Format output for CI system + # Example: storeIds=["store1", "store2"] + echo "storeIds=$(jq -c '.' changed_stores.json)" >> "$GITHUB_OUTPUT" + # Example: storeIdsFlag=--store-id store1 store2 + echo "storeIdsFlag=--store-id $STORES" >> "$GITHUB_OUTPUT" +``` + +Important considerations when using `store changed` command: + +1. `--condensed` flag prints just store IDs of changed stores. To see detailed change information in logs: + ```bash + # Remove --condensed flag to see why stores changed + yarn store changed --since $SINCE_SHA --to $TO_SHA >> changed_stores.json + echo "Changed stores report:" + cat changed_stores.json + ``` + Please note that as the format of the output changed, you should adjust the script to parse the store IDs from the new output. + +2. Handle cases when no stores changed: + ```bash + if [ -z "$STORES" ]; then + echo "No stores were affected by these changes" + echo "storeIds=[]" >> "$GITHUB_OUTPUT" + exit 0 + fi + ``` + +3. Use correct commit references for pull requests: + ```bash + # Base branch commit as starting point + --since ${{ github.event.pull_request.base.sha }} + # Branch HEAD as end point + --to ${{ github.event.pull_request.head.sha }} + ``` + +### 3. Running Tests ```yaml steps: - - name: Find affected stores - id: affectedStores + - name: Run tests for affected stores run: | - # Get list of changed stores - STORE_IDS=$(yarn store changed --since ${{ github.event.pull_request.base.sha }} --condensed) - - # Format for CI platform - echo "storeIds=$STORE_IDS" >> $GITHUB_OUTPUT - - # Create flag format for CLI - if [ "$STORE_IDS" != "[]" ]; then - STORE_FLAGS=$(echo $STORE_IDS | jq -r 'map("--store-id " + .) | join(" ")') - echo "storeIdsFlag=$STORE_FLAGS" >> $GITHUB_OUTPUT - fi + yarn store test --store-id $STORE_IDS ``` -::tip{title="Implementing in Other CI Systems"} -To implement change detection: -1. Run `yarn store changed --since ` -2. Parse the JSON output into your CI platform's variable format -3. Use these variables to control subsequent steps +## Continuous Deployment (CD) + +::tip +To learn how deployment works in detail, check out the [Deployment](/guides/multistore/tooling-and-concepts/deployment/deployment) guide. :: -### 3. Running Tests +The continuous deployment process ensures that your stores are built and deployed efficiently. Here's how it works: -Once you know which stores changed, run tests only for those stores: +### Deployment Triggers +There are several ways to configure when your stores get deployed: + +#### Automatic Deployment +Deploy automatically whenever code is pushed to the main branch: ```yaml -steps: - - name: Run integration tests - if: ${{ steps.affectedStores.outputs.storeIds != '[]' }} - run: | - # Install test dependencies - yarn playwright install --with-deps chromium - - # Run tests for affected stores - yarn store test ${{ steps.affectedStores.outputs.storeIdsFlag }} +on: + push: + branches: [main] # Deploy on every push to main +``` + +#### Manual Deployment +Allow manual deployments with optional store selection: +```yaml +on: + workflow_dispatch: + inputs: + store_ids: + description: 'Space separated list of store IDs to deploy' + required: false # When not provided, detect changed stores ``` -::tip{title="Cross-Platform Testing"} -Key considerations for any CI platform: -1. Install test dependencies -2. Use the store IDs from change detection -3. Set appropriate timeouts -4. Configure test result reporting +You can use the automatic deployment for staging and manual deployment for production environment. + +::tip Deployment Protection +For Github Actions, you can use deployment protection rules to require manual approval before deployments. Check out the Github [docs](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments) for more details. :: -### 4. Building Stores +### 1. Building and Deploying Stores -Before deployment, build the affected stores: +The `store deploy` command handles both building and deploying your stores. There's no need to run a separate build step: ```yaml steps: - - name: Build affected stores - if: ${{ steps.affectedStores.outputs.storeIds != '[]' }} + - name: Deploy stores run: | - yarn store build ${{ steps.affectedStores.outputs.storeIdsFlag }} + yarn store deploy \ + --cloud-username ${{ vars.CLOUD_USERNAME }} \ + --cloud-password ${{ secrets.CLOUD_PASSWORD }} \ + $storeIdsFlag \ + --verbose ``` -### 5. Parallel Deployment +### 2. Parallel Deployment -The final step is deploying the stores in parallel. Here's how to structure this in different CI systems: +For efficient deployment of multiple stores, use a matrix strategy: -::code-group -```yaml [GitHub Actions] +```yaml jobs: deploy: - name: Deploy ${{ matrix.store_id }} store strategy: matrix: - store_id: ${{ fromJson(needs.chooseStoresToDeploy.outputs.storeIds) }} + store_id: ${{ fromJson(storeIds) }} steps: - name: Deploy store - run: yarn store deploy --store-id ${{ matrix.store_id }} + run: | + yarn store deploy \ + --cloud-username ${{ vars.CLOUD_USERNAME }} \ + --cloud-password ${{ secrets.CLOUD_PASSWORD }} \ + --store-id ${{ matrix.store_id }} \ + --verbose ``` -```yaml [GitLab CI] -deploy: - parallel: - matrix: - - STORE_ID: $STORE_IDS # Define this variable in previous stage - script: - - yarn store deploy --store-id $STORE_ID -``` - -```yaml [Jenkins Pipeline] -stage('Deploy') { - steps { - script { - def storeIds = readJSON(text: STORE_IDS) - parallel storeIds.collectEntries { storeId -> - ["${storeId}" : { - sh "yarn store deploy --store-id ${storeId}" - }] - } - } - } -} -``` +## Advanced Topics + +### Understanding Change Detection + +The change detection system is a core part of our CI/CD pipeline, implemented in the CLI, with `yarn store changed` command, to ensure consistent behavior across different CI platforms. Here's how it works: + +The change detection system analyzes git differences and determines which stores are affected based on several rules: + +1. **Root Changes** + When files in the base applications change (e.g., `/apps/storefront-middleware/src/index.ts`), all stores inheriting from that application are affected, unless they override the changed file. + + Example: A change in base middleware: + - Changed file: `/apps/storefront-middleware/src/index.ts` + - Affected stores: All stores which don't have their own version of the file + +2. **Parent Store Changes** + When a parent store changes, all its child stores are affected, unless they override the changed file. + + Example: A change in parent store: + - Changed file: `/apps/stores/fashion-brand/middleware/index.ts` + - Affected stores: All stores which don't have their own version of the file + +3. **Direct Store Changes** + When files within a store directory change, only that store is affected. + + Example: A change in specific store: + - Changed file: `/apps/stores/sports-brand/middleware/index.ts` + - Affected store: only `sports-brand` + +4. **Dependency Changes** + Changes to dependency files (e.g., `yarn.lock`) affect all stores. + + Example: A change in dependencies: + - Changed file: `yarn.lock` + - Affected: All stores + +5. **Global Dependencies** + Changes to globally configured paths (e.g., shared packages) affect all stores. You can mark global dependencies for the `yarn store changed` command by adding the `--global-dependencies` flag. For example: + ```bash + # Mark all packages in the packages directory as global dependencies + yarn store changed --global-dependencies="packages/**" + ``` + +6. **File Overrides** + If a store overrides a file from its parent or base application, changes to the original file won't affect that store. + + Example: A file override: + - Changed file: `/apps/stores/fashion-brand/middleware/index.ts` + - Skipped: `fashion-brand-us` (has its own version of the file) + - Affected: Other child stores without overrides + +The system provides detailed information about why each store was affected: +- `STORE_CHANGED`: Direct changes to the store +- `ANCESTOR_CHANGED`: Changes in parent store or base application +- `PACKAGE_LOCK_CHANGED`: Dependency file changes +- `GLOBAL_DEPENDENCIES_CHANGED`: Changes in globally configured paths + +::tip +When debugging why a particular store was affected, run the `yarn store changed` command without the `--condensed` flag to see the detailed change report. You can also run the command locally to debug the changes. :: -::tip{title="Implementing Parallel Deployments"} -Key requirements for any CI platform: -1. Support for parallel job execution -2. Ability to share variables between jobs -3. Individual job retry capabilities -4. Proper error handling and reporting +::info Why not use Turbo for change detection? +While Turborepo is great for monorepo task orchestration, it can't handle our dynamic store composition. Our stores are composed into the `.out` directory, which is git-ignored. Turbo relies on git history for change detection, but it can't track how these dynamically composed stores in `.out` directory change. That's why we've implemented our own change detection system that understands store inheritance and file overrides. :: -## Version Control +### Why Parallel Store Deployments? -### CLI Version Management +We recommend running deployments in parallel (one job per store) for several reasons: -It's crucial to use a fixed CLI version across all environments: +1. **Isolation** + - Each store deployment runs in its own environment + - Failures in one store don't affect others + - Resource limits are per-store, preventing one store from consuming all resources -```yaml -steps: - - name: Get CLI version - id: cli_version - run: | - CLI_VERSION=$(jq -r '.dependencies["@alokai/cli"]' package.json) - echo "Using CLI version: $CLI_VERSION" - echo "CLI_VERSION=$CLI_VERSION" >> $GITHUB_OUTPUT - - - name: Deploy with specific version - run: npx @alokai/cli@${{ steps.cli_version.outputs.CLI_VERSION }} store deploy -``` +2. **Performance** + - Multiple stores deploy simultaneously + - Overall deployment time is significantly reduced -::warning{title="Version Consistency"} -Ensure the same CLI version is used in: -- Local development -- CI/CD pipelines -- Production deployments -:: +3. **Maintainability** + - Easy to retry failed deployments + - Clear logs per store + - Simpler debugging and monitoring -## Best Practices +### CLI-Driven Approach -1. **Environment Setup** - - Use dependency caching - - Set up proper timeout values - - Configure error reporting +Our CI/CD heavily relies on the CLI for several important reasons: -2. **Change Detection** - - Configure global dependencies properly - - Use appropriate git depth - - Handle branch merges correctly +1. **Platform Independence** + - The same commands work across all CI providers + - No need to rewrite logic for different platforms + - Consistent behavior everywhere -3. **Deployment Strategy** - - Implement proper rollback procedures - - Set up deployment verification - - Configure proper logging +2. **Local Build and Development Parity** + - Developers can run the same commands locally + - Easy to debug CI/CD issues + - No surprises between local and CI environments -## Common Pitfalls +3. **Encapsulated Logic** + - Complex operations are packaged in simple commands + - CI configuration focuses on workflow, not implementation + - Updates to deployment logic don't require CI changes -1. **Git Configuration** - - Insufficient git history depth - - Missing branch information - - Incorrect merge base detection +For example, instead of implementing store change detection in CI: +```yaml +# Don't do this +- name: Detect changes + run: | + # Complex git diff logic + # Parse file paths + # Check store inheritance + # Handle overrides +``` -2. **Resource Management** - - Excessive parallel jobs - - Missing timeout configurations - - Insufficient cleanup procedures +We use a single CLI command: +```yaml +# Do this instead +- name: Detect changes + run: yarn store changed --since $SINCE_SHA --to $TO_SHA +``` -3. **Error Handling** - - Missing failure notifications - - Incomplete error logs - - Poor retry mechanisms +This approach makes it easy to implement our CI/CD pipeline in any CI system that can run shell commands. ::card{title="Next: CLI Reference" icon="tabler:number-3-small" } #description From 66846511245942cdd7f51773f16be41437ff7efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Fri, 21 Feb 2025 15:55:18 +0700 Subject: [PATCH 3/7] chore: which stores have changed --- .../6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md index 272345f853..74566fdcb8 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md @@ -127,7 +127,7 @@ Your CI platform needs to support: full git history access for change detection, ### 2. Change Detection -The change detection step identifies which stores need deployment. Here's a simplified version of our approach: +The change detection step identifies which stores have changed. Here's a simplified version of our approach: ::tip While we recommend using change detection for efficiency, you can skip it and run actions for all stores using the `--all` flag: From 53f53772a46503026c1474b0a069d596f78e6176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Fri, 21 Feb 2025 15:57:36 +0700 Subject: [PATCH 4/7] docs: improve introduction --- .../6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md index 74566fdcb8..4f852301b0 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md @@ -7,7 +7,7 @@ navigation: # Deployment - CI/CD -Managing deployments for multiple stores can be challenging. This guide explains how Continuous Integration (CI) and Continuous Deployment (CD) work in a multistore setup, helping you create an efficient and reliable deployment process. +Running tests and deployments on your local machine works great during development, but let's be honest - what we really want is for these processes to happen automatically when we push our code. This guide explains how Continuous Integration (CI) and Continuous Deployment (CD) work in a multistore setup, helping you create an efficient and reliable deployment process that runs without manual intervention. **What You'll Learn** From 6f44a364fafe8e06df9ccc9cacada78975af1637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Fri, 21 Feb 2025 16:28:05 +0700 Subject: [PATCH 5/7] docs: describe a setup action on a higher level --- .../4.deployment/8.ci-cd.md | 101 +++++++----------- 1 file changed, 38 insertions(+), 63 deletions(-) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md index 4f852301b0..ccf6c63d10 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md @@ -41,78 +41,53 @@ Let's look at how continuous integration works in a multistore setup, using GitH First, we need to set up the environment. Our setup action handles several crucial steps: ::tip Why a Separate Setup Action? -We use a separate setup action to follow the DRY (Don't Repeat Yourself) principle, as these setup steps are used in multiple workflows - for instance `continuous-integration.yml` and `continuous-deployment.yml`. However, you can include these steps directly in your workflow if you prefer - there's no technical requirement to have them as a separate action. +We use a separate setup action to follow the DRY (Don't Repeat Yourself) principle, as these setup steps are used in multiple workflows. We've implemented it as a [composite action](https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action) to make it reusable across different workflows. :: -Here's how our setup action is defined: +The Setup action performs these steps in sequence: -```yaml -name: Setup repository -description: Installs all the packages and initializes environment variables +1. **Node.js Setup** + - Uses Node.js version specified in `.nvmrc` file -# Define required inputs for npm registry authentication -inputs: - npm_user: - description: Enterprise NPM registry user - required: true - npm_password: - description: Enterprise NPM registry password - required: true - npm_email: - description: Enterprise NPM registry email - required: true +2. **Cache Configuration** + - Sets up Yarn cache for `node_modules` directory to speed up installations + - Configures Turbo build cache for faster builds. Read more about Turbo CI caching [here](https://turbo.build/repo/docs/guides/ci-vendors). -runs: - using: composite - steps: - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version-file: ./.nvmrc - - # Configure Yarn cache to speed up installations - - name: Yarn cache - uses: actions/cache@v4 - with: - path: .yarn - key: storefront-yarn-cache - - # Set up Turbo cache for faster builds - - name: Cache turbo build setup - uses: actions/cache@v4 - with: - path: .turbo - key: starter-turbo-${{ github.sha }} - restore-keys: | - starter-turbo- - - # Configure access to private npm registry - - name: Configure NPM registry - shell: bash - run: | - npm install -g npm-cli-login; - npm-cli-login -u ${{ inputs.npm_user }} -p ${{ inputs.npm_password }} -e ${{ inputs.npm_email }} -r https://registrynpm.storefrontcloud.io || exit 1; - - # Install all project dependencies - - name: Install dependencies - shell: bash - # We use frozen-lockfile to ensure consistent dependencies across all environments - # This is important for CI/CD to avoid unexpected issues - # We run init.mjs to ensure the project is properly initialized - run: yarn install --frozen-lockfile --cache-folder .yarn && node init.mjs -``` +3. **NPM Registry Access** + - Configures access to private npm registry + - Uses provided credentials for authentication + ```bash + # Install npm-cli-login globally + npm install -g npm-cli-login + + # Configure access to Alokai Enterprise Registry + npm-cli-login \ + -u $NPM_USER \ + -p $NPM_PASSWORD \ + -e $NPM_EMAIL \ + -r "https://registrynpm.storefrontcloud.io" + + # You can verify the configuration by running the following command: + npm config get @alokai:registry + # Should return: https://registrynpm.storefrontcloud.i + ``` + +4. **Dependencies Installation** + - Installs project dependencies using Yarn + - Uses frozen lockfile for consistency + - Runs initialization script + ```bash + # Install dependencies with frozen lockfile + yarn install --frozen-lockfile --cache-folder .yarn + + # Run initialization script + node init.mjs + ``` -And here's how we use it in our workflow: +Here's how to use it in your workflow: ```yaml steps: - # 1. Check out your code - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Important: Need full git history for change detection - - # 2. Set up environment using our custom action - name: Install dependencies uses: ./.github/actions/setup with: From 45a8fd2592b9d4ce22fe0c12470cb729a03eb881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Fri, 21 Feb 2025 20:01:16 +0700 Subject: [PATCH 6/7] Update docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md Co-authored-by: Mateusz Ostafil --- .../6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md index ccf6c63d10..dc5e92142e 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md @@ -30,7 +30,7 @@ In a multistore setup, CI/CD is designed to: This targeted approach ensures: - Faster deployments (only changed stores are processed) - Efficient resource usage -- Reduced redundancy (unchanged stores are skipped in CI/CD pipeline) +- Less redundancy (unchanged stores are skipped in CI/CD pipeline) ## Continuous Integration (CI) From b140bed981ba9c0ba10f444b3fae862e565d6c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Tue, 25 Feb 2025 15:31:57 +0700 Subject: [PATCH 7/7] chore: remove ci part --- .../3.development/4.local-environment.md | 6 +- .../4.deployment/7.configuration.md | 2 +- .../4.deployment/{8.ci-cd.md => 8.cd.md} | 172 +----------------- 3 files changed, 14 insertions(+), 166 deletions(-) rename docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/{8.ci-cd.md => 8.cd.md} (57%) diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/3.development/4.local-environment.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/3.development/4.local-environment.md index d70bb50d84..43673b6811 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/3.development/4.local-environment.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/3.development/4.local-environment.md @@ -172,10 +172,10 @@ yarn store build --store-id=affected-store-id-1,affected-store-id-2 ``` :::tip -In the Continuous Integration pipeline, the affected stores are built and tested automatically. You can read more about it in the [Continuous Integration](/guides/multistore/tooling-and-concepts/deployment/ci-cd) guide. +In the Continuous Integration and Continuous Deployment pipelines, the affected stores are built and tested automatically. You can read more about it in the [CD Pipeline](/guides/multistore/tooling-and-concepts/deployment/cd) guide. ::: -3. **Debugging Inheritance** +1. **Debugging Inheritance** Use the `--verbose` flag to see detailed file resolution: ```bash yarn store build --store-id=my-store --verbose @@ -185,7 +185,7 @@ You can also use the `DEBUG=*` environment variable to get even more logs: DEBUG=* yarn store build --store-id=my-store ``` -4. **Inspect Store Composition** +1. **Inspect Store Composition** Examine how stores are composed in the `.out` directory: ```bash yarn store build --store-id=my-store --compose-only diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/7.configuration.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/7.configuration.md index b19af0516d..580854b474 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/7.configuration.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/7.configuration.md @@ -14,7 +14,7 @@ navigation: TODO #cta -:::docs-arrow-link{to="/guides/multistore/tooling-and-concepts/ci-cd"} +:::docs-arrow-link{to="/guides/multistore/tooling-and-concepts/cd"} Next ::: :: diff --git a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.cd.md similarity index 57% rename from docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md rename to docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.cd.md index dc5e92142e..8d8ac69f14 100644 --- a/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.ci-cd.md +++ b/docs/content/guides/6.multistore/2.tooling-and-concepts/4.deployment/8.cd.md @@ -1,18 +1,18 @@ --- -title: CI/CD +title: CD Pipeline layout: default navigation: icon: tabler:number-2-small --- -# Deployment - CI/CD +# Deployment - CD Pipeline -Running tests and deployments on your local machine works great during development, but let's be honest - what we really want is for these processes to happen automatically when we push our code. This guide explains how Continuous Integration (CI) and Continuous Deployment (CD) work in a multistore setup, helping you create an efficient and reliable deployment process that runs without manual intervention. +Running deployments on your local machine works great during development, but let's be honest - what we really want is for these processes to happen automatically when we push our code. This guide explains how Continuous Deployment (CD) works in a multistore setup, helping you create an efficient and reliable deployment process that runs without manual intervention. **What You'll Learn** ::list{type="success"} -- How to set up CI/CD pipeline using GitHub Actions +- How to set up CD pipeline using GitHub Actions - How to detect and process only changed stores - How to efficiently deploy multiple stores in parallel - Advanced topics like change detection mechanism and CLI-driven approach @@ -20,168 +20,16 @@ Running tests and deployments on your local machine works great during developme ## Core Concepts -### What is CI/CD in Multistore? +### What is CD in Multistore? -In a multistore setup, CI/CD is designed to: +In a multistore setup, CD is designed to: 1. Automatically detect which stores have changed -2. Run tests only for affected stores -3. Build and deploy only the changed stores +2. Build and deploy only the changed stores This targeted approach ensures: -- Faster deployments (only changed stores are processed) +- Faster deployments - Efficient resource usage -- Less redundancy (unchanged stores are skipped in CI/CD pipeline) - -## Continuous Integration (CI) - -Let's look at how continuous integration works in a multistore setup, using GitHub Actions as an example while explaining how to adapt each step for other CI platforms. - -### 1. Setting Up Dependencies - -First, we need to set up the environment. Our setup action handles several crucial steps: - -::tip Why a Separate Setup Action? -We use a separate setup action to follow the DRY (Don't Repeat Yourself) principle, as these setup steps are used in multiple workflows. We've implemented it as a [composite action](https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action) to make it reusable across different workflows. -:: - -The Setup action performs these steps in sequence: - -1. **Node.js Setup** - - Uses Node.js version specified in `.nvmrc` file - -2. **Cache Configuration** - - Sets up Yarn cache for `node_modules` directory to speed up installations - - Configures Turbo build cache for faster builds. Read more about Turbo CI caching [here](https://turbo.build/repo/docs/guides/ci-vendors). - -3. **NPM Registry Access** - - Configures access to private npm registry - - Uses provided credentials for authentication - ```bash - # Install npm-cli-login globally - npm install -g npm-cli-login - - # Configure access to Alokai Enterprise Registry - npm-cli-login \ - -u $NPM_USER \ - -p $NPM_PASSWORD \ - -e $NPM_EMAIL \ - -r "https://registrynpm.storefrontcloud.io" - - # You can verify the configuration by running the following command: - npm config get @alokai:registry - # Should return: https://registrynpm.storefrontcloud.i - ``` - -4. **Dependencies Installation** - - Installs project dependencies using Yarn - - Uses frozen lockfile for consistency - - Runs initialization script - ```bash - # Install dependencies with frozen lockfile - yarn install --frozen-lockfile --cache-folder .yarn - - # Run initialization script - node init.mjs - ``` - -Here's how to use it in your workflow: - -```yaml -steps: - - name: Install dependencies - uses: ./.github/actions/setup - with: - npm_user: ${{ vars.NPM_USER }} - npm_password: ${{ secrets.NPM_PASS }} - npm_email: ${{ vars.NPM_EMAIL }} -``` - -::tip Adapting for Other CI Platforms -Your CI platform needs to support: full git history access for change detection, Node.js environment setup, Yarn cache configuration, Turbo build cache setup for faster builds, and access to Alokai Enterprise Registry. -:: - -### 2. Change Detection - -The change detection step identifies which stores have changed. Here's a simplified version of our approach: - -::tip -While we recommend using change detection for efficiency, you can skip it and run actions for all stores using the `--all` flag: -```bash -# Run tests for all stores regardless of changes -yarn store test --all - -# Deploy all stores -yarn store deploy --all -``` -:: - -```yaml -name: Affected Stores -description: Determines which stores are affected - -inputs: - since: - description: Base commit for changes - required: false - to: - description: Head commit for changes - required: false - -runs: - using: composite - steps: - - name: Find affected stores - run: | - # Basic change detection - # Determine affected stores using the storefront CLI - yarn store changed --condensed --since ${{ inputs.since }} --to ${{ inputs.to }} > changed_stores.json - - # Extract store IDs from the output - STORES=$(jq -r '. | join(" ")' changed_stores.json) - - # Format output for CI system - # Example: storeIds=["store1", "store2"] - echo "storeIds=$(jq -c '.' changed_stores.json)" >> "$GITHUB_OUTPUT" - # Example: storeIdsFlag=--store-id store1 store2 - echo "storeIdsFlag=--store-id $STORES" >> "$GITHUB_OUTPUT" -``` - -Important considerations when using `store changed` command: - -1. `--condensed` flag prints just store IDs of changed stores. To see detailed change information in logs: - ```bash - # Remove --condensed flag to see why stores changed - yarn store changed --since $SINCE_SHA --to $TO_SHA >> changed_stores.json - echo "Changed stores report:" - cat changed_stores.json - ``` - Please note that as the format of the output changed, you should adjust the script to parse the store IDs from the new output. - -2. Handle cases when no stores changed: - ```bash - if [ -z "$STORES" ]; then - echo "No stores were affected by these changes" - echo "storeIds=[]" >> "$GITHUB_OUTPUT" - exit 0 - fi - ``` - -3. Use correct commit references for pull requests: - ```bash - # Base branch commit as starting point - --since ${{ github.event.pull_request.base.sha }} - # Branch HEAD as end point - --to ${{ github.event.pull_request.head.sha }} - ``` - -### 3. Running Tests - -```yaml -steps: - - name: Run tests for affected stores - run: | - yarn store test --store-id $STORE_IDS -``` +- Less redundancy (unchanged stores are skipped in CD pipeline) ## Continuous Deployment (CD) @@ -343,7 +191,7 @@ We recommend running deployments in parallel (one job per store) for several rea Our CI/CD heavily relies on the CLI for several important reasons: 1. **Platform Independence** - - The same commands work across all CI providers + - The same commands work across all platforms - No need to rewrite logic for different platforms - Consistent behavior everywhere