11# ============================================================================
2- # MODULE 1: ANTI-PATTERN - Sequential Pipeline (The "Before" State)
2+ # MODULE 1: Workflow Orchestration Best Practices
33# ============================================================================
4- # This config demonstrates what NOT to do. Every job waits for the previous
5- # one, even when there's no real dependency. We reinstall deps in every job .
4+ # Fan-out/Fan-in pattern: Build once, test in parallel, converge to deploy.
5+ # Uses workspace to share node_modules across jobs (install once, use many) .
66#
7- # PAIN POINTS TO OBSERVE IN CIRCLECI UI:
8- # - Total time = sum of all jobs (no parallelism)
9- # - Each job reinstalls node_modules (~30-60 sec wasted per job)
10- # - Pipeline visualization shows a straight line, not a diamond
7+ # WORKFLOW VISUALIZATION:
8+ #
9+ # require-approval=true (default):
10+ # ┌─► lint ──────────┐
11+ # │ │
12+ # build ──────────►├─► test-unit ─────┼──► [approve-deploy] ──► deploy-simulation
13+ # │ │
14+ # ├─► test-integ ────┤
15+ # │ │
16+ # └─► test-e2e ──────┘
17+ #
18+ # require-approval=false (auto-deploy):
19+ # ┌─► lint ──────────┐
20+ # │ │
21+ # build ──────────►├─► test-unit ─────┼──────► deploy-simulation
22+ # │ │
23+ # ├─► test-integ ────┤
24+ # │ │
25+ # └─► test-e2e ──────┘
26+ #
27+ # Total time: ~2-3 min (parallel) vs ~6-8 min (sequential)
1128# ============================================================================
1229
1330version : 2.1
1431
32+ # ============================================================================
33+ # PIPELINE PARAMETERS: Feature flags configurable via API, UI, or triggers
34+ # ============================================================================
35+ parameters :
36+ require-approval :
37+ type : boolean
38+ default : true
39+ description : " Require manual approval before deploy (false = auto-deploy)"
40+
1541jobs :
42+ # --------------------------------------------------------------------------
43+ # BUILD: Install deps once, persist to workspace for all downstream jobs
44+ # --------------------------------------------------------------------------
1645 build :
1746 docker :
1847 - image : cimg/node:20.18
1948 steps :
2049 - checkout
50+ # CACHING: Restores node_modules from cache if package-lock.json unchanged
51+ # First key = exact match, second key = partial fallback (may need npm ci)
52+ - restore_cache :
53+ keys :
54+ - deps-v1-{{ checksum "package-lock.json" }}
55+ - deps-v1-
2156 - run :
2257 name : Install dependencies
2358 command : npm ci
59+ # Save to cache after install; only runs if key doesn't already exist
60+ - save_cache :
61+ key : deps-v1-{{ checksum "package-lock.json" }}
62+ paths :
63+ - node_modules
2464 - run :
2565 name : Build application
2666 command : npm run build
67+ # KEY CONCEPT: Persist workspace so downstream jobs skip npm ci
68+ - persist_to_workspace :
69+ root : .
70+ paths :
71+ - node_modules
72+ - dist
2773
74+ # --------------------------------------------------------------------------
75+ # PARALLEL JOBS: All attach workspace, run simultaneously after build
76+ # --------------------------------------------------------------------------
2877 lint :
2978 docker :
3079 - image : cimg/node:20.18
3180 steps :
3281 - checkout
33- - run :
34- name : Install dependencies (again!)
35- command : npm ci # WASTE: Already installed in build
82+ - attach_workspace :
83+ at : .
3684 - run :
3785 name : Run linter
3886 command : npm run lint
@@ -42,42 +90,83 @@ jobs:
4290 - image : cimg/node:20.18
4391 steps :
4492 - checkout
45- - run :
46- name : Install dependencies (again!)
47- command : npm ci # WASTE: Third time installing
93+ - attach_workspace :
94+ at : .
4895 - run :
4996 name : Run unit tests
5097 command : npm run test:unit
98+ # store_test_results: Uploads JUnit XML for CircleCI's Test Insights tab
99+ # Enables test timing analysis, flaky test detection, and historical trends
100+ - store_test_results :
101+ path : test-results
102+ - store_artifacts :
103+ path : coverage
104+ destination : unit-coverage
51105
52106 test-integration :
53107 docker :
54108 - image : cimg/node:20.18
55109 steps :
56110 - checkout
57- - run :
58- name : Install dependencies (again!)
59- command : npm ci # WASTE: Fourth time
111+ - attach_workspace :
112+ at : .
60113 - run :
61114 name : Run integration tests
62115 command : npm run test:integration
116+ # Parses test XML for the Insights dashboard (separate from artifacts)
117+ - store_test_results :
118+ path : test-results
63119
64120 test-e2e :
65121 docker :
66122 - image : cimg/node:20.18
67123 steps :
68124 - checkout
69- - run :
70- name : Install dependencies (again!)
71- command : npm ci # WASTE: Fifth time!
125+ - attach_workspace :
126+ at : .
72127 - run :
73128 name : Run E2E tests
74129 command : npm run test:e2e
130+ # Test results enable automatic test splitting in future parallelism configs
131+ - store_test_results :
132+ path : test-results
133+
134+ # --------------------------------------------------------------------------
135+ # DEPLOY SIMULATION: Fan-in - requires ALL parallel jobs to pass
136+ # --------------------------------------------------------------------------
137+ deploy-simulation :
138+ docker :
139+ - image : cimg/node:20.18
140+ steps :
141+ - checkout
142+ - attach_workspace :
143+ at : .
144+ - run :
145+ name : Deploy Robot Fleet API (simulated)
146+ command : |
147+ echo "==========================================="
148+ echo " DEPLOYING GLOBOMANTICS ROBOT FLEET API"
149+ echo "==========================================="
150+ # CIRCLE_BRANCH: Git branch that triggered this pipeline
151+ echo " Branch: ${CIRCLE_BRANCH}"
152+ # CIRCLE_SHA1: Full 40-char Git commit SHA (truncated here to 7)
153+ echo " Commit: ${CIRCLE_SHA1:0:7}"
154+ # CIRCLE_BUILD_NUM: Auto-incrementing build number for this project
155+ echo " Build: ${CIRCLE_BUILD_NUM}"
156+ echo "==========================================="
157+ echo "Deployment successful! (simulated)"
75158
76159# ============================================================================
77- # WORKFLOW: Everything runs sequentially - SLOW!
160+ # WORKFLOW: Fan-out after build, fan-in before deploy
78161# ============================================================================
162+ # Two workflows controlled by pipeline parameter - only one runs at a time
79163workflows :
80- m1-sequential-anti-pattern :
164+ # --------------------------------------------------------------------------
165+ # WORKFLOW 1: With approval gate (default when require-approval=true)
166+ # --------------------------------------------------------------------------
167+ m1-build-test-deploy :
168+ # WHEN at workflow level: entire workflow only runs if condition is true
169+ when : << pipeline.parameters.require-approval >>
81170 jobs :
82171 - build :
83172 filters :
@@ -86,31 +175,102 @@ workflows:
86175 - main
87176 - /feature\/.*/
88177
89- # ANTI-PATTERN: lint waits for build, but doesn't need build output
178+ # FAN-OUT: These 4 jobs all require build, so they run in PARALLEL
90179 - lint :
91180 requires :
92181 - build
93182
94- # ANTI-PATTERN: These tests don't depend on each other, yet run sequentially
95183 - test-unit :
96184 requires :
97- - lint
185+ - build
98186
99187 - test-integration :
100188 requires :
189+ - build
190+
191+ - test-e2e :
192+ requires :
193+ - build
194+
195+ # APPROVAL GATE: Pauses workflow until someone clicks "Approve" in UI
196+ # type: approval = special job with no compute cost while waiting
197+ - approve-deploy :
198+ type : approval
199+ requires :
200+ - lint
101201 - test-unit
202+ - test-integration
203+ - test-e2e
204+ filters :
205+ branches :
206+ only : main
207+
208+ # FAN-IN: Deploy only after manual approval
209+ - deploy-simulation :
210+ requires :
211+ - approve-deploy
212+ filters :
213+ branches :
214+ only : main
215+
216+ # --------------------------------------------------------------------------
217+ # WORKFLOW 2: Auto-deploy without approval (when require-approval=false)
218+ # --------------------------------------------------------------------------
219+ m1-build-test-deploy-auto :
220+ # UNLESS at workflow level: runs when condition is false (inverse of when)
221+ unless : << pipeline.parameters.require-approval >>
222+ jobs :
223+ - build :
224+ filters :
225+ branches :
226+ only :
227+ - main
228+ - /feature\/.*/
229+
230+ - lint :
231+ requires :
232+ - build
233+
234+ - test-unit :
235+ requires :
236+ - build
237+
238+ - test-integration :
239+ requires :
240+ - build
102241
103242 - test-e2e :
104243 requires :
244+ - build
245+
246+ # FAN-IN: Deploy directly after tests pass (no approval gate)
247+ - deploy-simulation :
248+ requires :
249+ - lint
250+ - test-unit
105251 - test-integration
252+ - test-e2e
253+ filters :
254+ branches :
255+ only : main
106256
107257# ============================================================================
108- # WHAT'S WRONG HERE (Module 1 Learning Points):
258+ # MODULE 1 KEY CONCEPTS DEMONSTRATED:
259+ #
260+ # 1. REQUIRES KEYWORD: Creates job dependencies (build → tests → deploy)
261+ # 2. FAN-OUT: Multiple jobs with same requirement run in parallel
262+ # 3. FAN-IN: Single job requiring multiple predecessors waits for all
263+ # 4. BRANCH FILTERS: Control which branches trigger which jobs
264+ # 5. WORKSPACE: Share artifacts between jobs (eliminates redundant npm ci)
265+ # 6. APPROVAL GATES: type: approval pauses workflow for manual approval
266+ # 7. PIPELINE PARAMETERS: Feature flags to control workflow behavior
267+ # 8. CONDITIONAL WORKFLOWS: when/unless at WORKFLOW level toggles entire flows
268+ # (Note: when/unless must be at workflow level, not individual job level)
109269#
110- # 1. FALSE DEPENDENCIES: lint doesn't need build output - just source code
111- # 2. NO PARALLELISM: All test jobs could run at the same time
112- # 3. NO WORKSPACE: npm ci runs 5 times instead of once
113- # 4. TOTAL TIME: ~6-8 min sequential vs ~2-3 min with fan-out
270+ # TRIGGERING WITH PARAMETERS (via API or curl):
271+ # curl -X POST https://circleci.com/api/v2/project/gh/OWNER/REPO/pipeline \
272+ # -H "Circle-Token: $TOKEN" -H "Content-Type: application/json" \
273+ # -d '{"parameters": {"require-approval": false}}'
114274#
115- # Next config (02) shows the fix using fan-out/fan-in patterns .
275+ # CREDIT CONSUMPTION: Same as sequential! You pay for compute time, not wall time .
116276# ============================================================================
0 commit comments