|
| 1 | +--- |
| 2 | +title: CD Pipeline |
| 3 | +layout: default |
| 4 | +navigation: |
| 5 | + icon: tabler:number-2-small |
| 6 | +--- |
| 7 | + |
| 8 | +# Deployment - CD Pipeline |
| 9 | + |
| 10 | +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. |
| 11 | + |
| 12 | +**What You'll Learn** |
| 13 | + |
| 14 | +::list{type="success"} |
| 15 | +- How to set up CD pipeline using GitHub Actions |
| 16 | +- How to detect and process only changed stores |
| 17 | +- How to efficiently deploy multiple stores in parallel |
| 18 | +- Advanced topics like change detection mechanism and CLI-driven approach |
| 19 | +:: |
| 20 | + |
| 21 | +## Core Concepts |
| 22 | + |
| 23 | +### What is CD in Multistore? |
| 24 | + |
| 25 | +In a multistore setup, CD is designed to: |
| 26 | +1. Automatically detect which stores have changed |
| 27 | +2. Build and deploy only the changed stores |
| 28 | + |
| 29 | +This targeted approach ensures: |
| 30 | +- Faster deployments |
| 31 | +- Efficient resource usage |
| 32 | +- Less redundancy (unchanged stores are skipped in CD pipeline) |
| 33 | + |
| 34 | +## Continuous Deployment (CD) |
| 35 | + |
| 36 | +::tip |
| 37 | +To learn how deployment works in detail, check out the [Deployment](/guides/multistore/tooling-and-concepts/deployment/deployment) guide. |
| 38 | +:: |
| 39 | + |
| 40 | +The continuous deployment process ensures that your stores are built and deployed efficiently. Here's how it works: |
| 41 | + |
| 42 | +### Deployment Triggers |
| 43 | + |
| 44 | +There are several ways to configure when your stores get deployed: |
| 45 | + |
| 46 | +#### Automatic Deployment |
| 47 | +Deploy automatically whenever code is pushed to the main branch: |
| 48 | +```yaml |
| 49 | +on: |
| 50 | + push: |
| 51 | + branches: [main] # Deploy on every push to main |
| 52 | +``` |
| 53 | +
|
| 54 | +#### Manual Deployment |
| 55 | +Allow manual deployments with optional store selection: |
| 56 | +```yaml |
| 57 | +on: |
| 58 | + workflow_dispatch: |
| 59 | + inputs: |
| 60 | + store_ids: |
| 61 | + description: 'Space separated list of store IDs to deploy' |
| 62 | + required: false # When not provided, detect changed stores |
| 63 | +``` |
| 64 | +
|
| 65 | +You can use the automatic deployment for staging and manual deployment for production environment. |
| 66 | +
|
| 67 | +::tip Deployment Protection |
| 68 | +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. |
| 69 | +:: |
| 70 | +
|
| 71 | +### 1. Building and Deploying Stores |
| 72 | +
|
| 73 | +The `store deploy` command handles both building and deploying your stores. There's no need to run a separate build step: |
| 74 | + |
| 75 | +```yaml |
| 76 | +steps: |
| 77 | + - name: Deploy stores |
| 78 | + run: | |
| 79 | + yarn store deploy \ |
| 80 | + --cloud-username ${{ vars.CLOUD_USERNAME }} \ |
| 81 | + --cloud-password ${{ secrets.CLOUD_PASSWORD }} \ |
| 82 | + $storeIdsFlag \ |
| 83 | + --verbose |
| 84 | +``` |
| 85 | + |
| 86 | +### 2. Parallel Deployment |
| 87 | + |
| 88 | +For efficient deployment of multiple stores, use a matrix strategy: |
| 89 | + |
| 90 | +```yaml |
| 91 | +jobs: |
| 92 | + deploy: |
| 93 | + strategy: |
| 94 | + matrix: |
| 95 | + store_id: ${{ fromJson(storeIds) }} |
| 96 | + steps: |
| 97 | + - name: Deploy store |
| 98 | + run: | |
| 99 | + yarn store deploy \ |
| 100 | + --cloud-username ${{ vars.CLOUD_USERNAME }} \ |
| 101 | + --cloud-password ${{ secrets.CLOUD_PASSWORD }} \ |
| 102 | + --store-id ${{ matrix.store_id }} \ |
| 103 | + --verbose |
| 104 | +``` |
| 105 | + |
| 106 | +## Advanced Topics |
| 107 | + |
| 108 | +### Understanding Change Detection |
| 109 | + |
| 110 | +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: |
| 111 | + |
| 112 | +The change detection system analyzes git differences and determines which stores are affected based on several rules: |
| 113 | + |
| 114 | +1. **Root Changes** |
| 115 | + 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. |
| 116 | + |
| 117 | + Example: A change in base middleware: |
| 118 | + - Changed file: `/apps/storefront-middleware/src/index.ts` |
| 119 | + - Affected stores: All stores which don't have their own version of the file |
| 120 | + |
| 121 | +2. **Parent Store Changes** |
| 122 | + When a parent store changes, all its child stores are affected, unless they override the changed file. |
| 123 | + |
| 124 | + Example: A change in parent store: |
| 125 | + - Changed file: `/apps/stores/fashion-brand/middleware/index.ts` |
| 126 | + - Affected stores: All stores which don't have their own version of the file |
| 127 | + |
| 128 | +3. **Direct Store Changes** |
| 129 | + When files within a store directory change, only that store is affected. |
| 130 | + |
| 131 | + Example: A change in specific store: |
| 132 | + - Changed file: `/apps/stores/sports-brand/middleware/index.ts` |
| 133 | + - Affected store: only `sports-brand` |
| 134 | + |
| 135 | +4. **Dependency Changes** |
| 136 | + Changes to dependency files (e.g., `yarn.lock`) affect all stores. |
| 137 | + |
| 138 | + Example: A change in dependencies: |
| 139 | + - Changed file: `yarn.lock` |
| 140 | + - Affected: All stores |
| 141 | + |
| 142 | +5. **Global Dependencies** |
| 143 | + 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: |
| 144 | + ```bash |
| 145 | + # Mark all packages in the packages directory as global dependencies |
| 146 | + yarn store changed --global-dependencies="packages/**" |
| 147 | + ``` |
| 148 | + |
| 149 | +6. **File Overrides** |
| 150 | + If a store overrides a file from its parent or base application, changes to the original file won't affect that store. |
| 151 | + |
| 152 | + Example: A file override: |
| 153 | + - Changed file: `/apps/stores/fashion-brand/middleware/index.ts` |
| 154 | + - Skipped: `fashion-brand-us` (has its own version of the file) |
| 155 | + - Affected: Other child stores without overrides |
| 156 | + |
| 157 | +The system provides detailed information about why each store was affected: |
| 158 | +- `STORE_CHANGED`: Direct changes to the store |
| 159 | +- `ANCESTOR_CHANGED`: Changes in parent store or base application |
| 160 | +- `PACKAGE_LOCK_CHANGED`: Dependency file changes |
| 161 | +- `GLOBAL_DEPENDENCIES_CHANGED`: Changes in globally configured paths |
| 162 | + |
| 163 | +::tip |
| 164 | +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. |
| 165 | +:: |
| 166 | + |
| 167 | +::info Why not use Turbo for change detection? |
| 168 | +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. |
| 169 | +:: |
| 170 | + |
| 171 | +### Why Parallel Store Deployments? |
| 172 | + |
| 173 | +We recommend running deployments in parallel (one job per store) for several reasons: |
| 174 | + |
| 175 | +1. **Isolation** |
| 176 | + - Each store deployment runs in its own environment |
| 177 | + - Failures in one store don't affect others |
| 178 | + - Resource limits are per-store, preventing one store from consuming all resources |
| 179 | + |
| 180 | +2. **Performance** |
| 181 | + - Multiple stores deploy simultaneously |
| 182 | + - Overall deployment time is significantly reduced |
| 183 | + |
| 184 | +3. **Maintainability** |
| 185 | + - Easy to retry failed deployments |
| 186 | + - Clear logs per store |
| 187 | + - Simpler debugging and monitoring |
| 188 | + |
| 189 | +### CLI-Driven Approach |
| 190 | + |
| 191 | +Our CI/CD heavily relies on the CLI for several important reasons: |
| 192 | + |
| 193 | +1. **Platform Independence** |
| 194 | + - The same commands work across all platforms |
| 195 | + - No need to rewrite logic for different platforms |
| 196 | + - Consistent behavior everywhere |
| 197 | + |
| 198 | +2. **Local Build and Development Parity** |
| 199 | + - Developers can run the same commands locally |
| 200 | + - Easy to debug CI/CD issues |
| 201 | + - No surprises between local and CI environments |
| 202 | + |
| 203 | +3. **Encapsulated Logic** |
| 204 | + - Complex operations are packaged in simple commands |
| 205 | + - CI configuration focuses on workflow, not implementation |
| 206 | + - Updates to deployment logic don't require CI changes |
| 207 | + |
| 208 | +For example, instead of implementing store change detection in CI: |
| 209 | +```yaml |
| 210 | +# Don't do this |
| 211 | +- name: Detect changes |
| 212 | + run: | |
| 213 | + # Complex git diff logic |
| 214 | + # Parse file paths |
| 215 | + # Check store inheritance |
| 216 | + # Handle overrides |
| 217 | +``` |
| 218 | + |
| 219 | +We use a single CLI command: |
| 220 | +```yaml |
| 221 | +# Do this instead |
| 222 | +- name: Detect changes |
| 223 | + run: yarn store changed --since $SINCE_SHA --to $TO_SHA |
| 224 | +``` |
| 225 | + |
| 226 | +This approach makes it easy to implement our CI/CD pipeline in any CI system that can run shell commands. |
| 227 | + |
| 228 | +::card{title="Next: CLI Reference" icon="tabler:number-3-small" } |
| 229 | +#description |
| 230 | +Learn more about the CLI commands used in CI/CD pipelines. |
| 231 | + |
| 232 | +#cta |
| 233 | +:::docs-arrow-link{to="/guides/multistore/tooling-and-concepts/cli-reference"} |
| 234 | +Next |
| 235 | +::: |
| 236 | +:: |
0 commit comments