{"id":"249715cd-823e-4a71-93ad-5415a74d2417","shortId":"LYLTwY","kind":"skill","title":"Ci Cd And Automation","tagline":"Agent Skills skill by Addyosmani","description":"# CI/CD and Automation\n\n## Overview\n\nAutomate quality gates so that no change reaches production without passing tests, lint, type checking, and build. CI/CD is the enforcement mechanism for every other skill — it catches what humans and agents miss, and it does so consistently on every single change.\n\n**Shift Left:** Catch problems as early in the pipeline as possible. A bug caught in linting costs minutes; the same bug caught in production costs hours. Move checks upstream — static analysis before tests, tests before staging, staging before production.\n\n**Faster is Safer:** Smaller batches and more frequent releases reduce risk, not increase it. A deployment with 3 changes is easier to debug than one with 30. Frequent releases build confidence in the release process itself.\n\n## When to Use\n\n- Setting up a new project's CI pipeline\n- Adding or modifying automated checks\n- Configuring deployment pipelines\n- When a change should trigger automated verification\n- Debugging CI failures\n\n## The Quality Gate Pipeline\n\nEvery change goes through these gates before merge:\n\n```\nPull Request Opened\n    │\n    ▼\n┌─────────────────┐\n│   LINT CHECK     │  eslint, prettier\n│   ↓ pass         │\n│   TYPE CHECK     │  tsc --noEmit\n│   ↓ pass         │\n│   UNIT TESTS     │  jest/vitest\n│   ↓ pass         │\n│   BUILD          │  npm run build\n│   ↓ pass         │\n│   INTEGRATION    │  API/DB tests\n│   ↓ pass         │\n│   E2E (optional) │  Playwright/Cypress\n│   ↓ pass         │\n│   SECURITY AUDIT │  npm audit\n│   ↓ pass         │\n│   BUNDLE SIZE    │  bundlesize check\n└─────────────────┘\n    │\n    ▼\n  Ready for review\n```\n\n**No gate can be skipped.** If lint fails, fix lint — don't disable the rule. If a test fails, fix the code — don't skip the test.\n\n## GitHub Actions Configuration\n\n### Basic CI Pipeline\n\n```yaml\n# .github/workflows/ci.yml\nname: CI\n\non:\n  pull_request:\n    branches: [main]\n  push:\n    branches: [main]\n\njobs:\n  quality:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '22'\n          cache: 'npm'\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Lint\n        run: npm run lint\n\n      - name: Type check\n        run: npx tsc --noEmit\n\n      - name: Test\n        run: npm test -- --coverage\n\n      - name: Build\n        run: npm run build\n\n      - name: Security audit\n        run: npm audit --audit-level=high\n```\n\n### With Database Integration Tests\n\n```yaml\n  integration:\n    runs-on: ubuntu-latest\n    services:\n      postgres:\n        image: postgres:16\n        env:\n          POSTGRES_DB: testdb\n          POSTGRES_USER: ci_user\n          POSTGRES_PASSWORD: ${{ secrets.CI_DB_PASSWORD }}\n        ports:\n          - 5432:5432\n        options: >-\n          --health-cmd pg_isready\n          --health-interval 10s\n          --health-timeout 5s\n          --health-retries 5\n\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '22'\n          cache: 'npm'\n      - run: npm ci\n      - name: Run migrations\n        run: npx prisma migrate deploy\n        env:\n          DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb\n      - name: Integration tests\n        run: npm run test:integration\n        env:\n          DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb\n```\n\n> **Note:** Even for CI-only test databases, use GitHub Secrets for credentials rather than hardcoding values. This builds good habits and prevents accidental reuse of test credentials in other contexts.\n\n### E2E Tests\n\n```yaml\n  e2e:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '22'\n          cache: 'npm'\n      - run: npm ci\n      - name: Install Playwright\n        run: npx playwright install --with-deps chromium\n      - name: Build\n        run: npm run build\n      - name: Run E2E tests\n        run: npx playwright test\n      - uses: actions/upload-artifact@v4\n        if: failure()\n        with:\n          name: playwright-report\n          path: playwright-report/\n```\n\n## Feeding CI Failures Back to Agents\n\nThe power of CI with AI agents is the feedback loop. When CI fails:\n\n```\nCI fails\n    │\n    ▼\nCopy the failure output\n    │\n    ▼\nFeed it to the agent:\n\"The CI pipeline failed with this error:\n[paste specific error]\nFix the issue and verify locally before pushing again.\"\n    │\n    ▼\nAgent fixes → pushes → CI runs again\n```\n\n**Key patterns:**\n\n```\nLint failure → Agent runs `npm run lint --fix` and commits\nType error  → Agent reads the error location and fixes the type\nTest failure → Agent follows debugging-and-error-recovery skill\nBuild error → Agent checks config and dependencies\n```\n\n## Deployment Strategies\n\n### Preview Deployments\n\nEvery PR gets a preview deployment for manual testing:\n\n```yaml\n# Deploy preview on PR (Vercel/Netlify/etc.)\ndeploy-preview:\n  runs-on: ubuntu-latest\n  if: github.event_name == 'pull_request'\n  steps:\n    - uses: actions/checkout@v4\n    - name: Deploy preview\n      run: npx vercel --token=${{ secrets.VERCEL_TOKEN }}\n```\n\n### Feature Flags\n\nFeature flags decouple deployment from release. Deploy incomplete or risky features behind flags so you can:\n\n- **Ship code without enabling it.** Merge to main early, enable when ready.\n- **Roll back without redeploying.** Disable the flag instead of reverting code.\n- **Canary new features.** Enable for 1% of users, then 10%, then 100%.\n- **Run A/B tests.** Compare behavior with and without the feature.\n\n```typescript\n// Simple feature flag pattern\nif (featureFlags.isEnabled('new-checkout-flow', { userId })) {\n  return renderNewCheckout();\n}\nreturn renderLegacyCheckout();\n```\n\n**Flag lifecycle:** Create → Enable for testing → Canary → Full rollout → Remove the flag and dead code. Flags that live forever become technical debt — set a cleanup date when you create them.\n\n### Staged Rollouts\n\n```\nPR merged to main\n    │\n    ▼\n  Staging deployment (auto)\n    │ Manual verification\n    ▼\n  Production deployment (manual trigger or auto after staging)\n    │\n    ▼\n  Monitor for errors (15-minute window)\n    │\n    ├── Errors detected → Rollback\n    └── Clean → Done\n```\n\n### Rollback Plan\n\nEvery deployment should be reversible:\n\n```yaml\n# Manual rollback workflow\nname: Rollback\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: 'Version to rollback to'\n        required: true\n\njobs:\n  rollback:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Rollback deployment\n        run: |\n          # Deploy the specified previous version\n          npx vercel rollback ${{ inputs.version }}\n```\n\n## Environment Management\n\n```\n.env.example       → Committed (template for developers)\n.env                → NOT committed (local development)\n.env.test           → Committed (test environment, no real secrets)\nCI secrets          → Stored in GitHub Secrets / vault\nProduction secrets  → Stored in deployment platform / vault\n```\n\nCI should never have production secrets. Use separate secrets for CI testing.\n\n## Automation Beyond CI\n\n### Dependabot / Renovate\n\n```yaml\n# .github/dependabot.yml\nversion: 2\nupdates:\n  - package-ecosystem: npm\n    directory: /\n    schedule:\n      interval: weekly\n    open-pull-requests-limit: 5\n```\n\n### Build Cop Role\n\nDesignate someone responsible for keeping CI green. When the build breaks, the Build Cop's job is to fix or revert — not the person whose change caused the break. This prevents broken builds from accumulating while everyone assumes someone else will fix it.\n\n### PR Checks\n\n- **Required reviews:** At least 1 approval before merge\n- **Required status checks:** CI must pass before merge\n- **Branch protection:** No force-pushes to main\n- **Auto-merge:** If all checks pass and approved, merge automatically\n\n## CI Optimization\n\nWhen the pipeline exceeds 10 minutes, apply these strategies in order of impact:\n\n```\nSlow CI pipeline?\n├── Cache dependencies\n│   └── Use actions/cache or setup-node cache option for node_modules\n├── Run jobs in parallel\n│   └── Split lint, typecheck, test, build into separate parallel jobs\n├── Only run what changed\n│   └── Use path filters to skip unrelated jobs (e.g., skip e2e for docs-only PRs)\n├── Use matrix builds\n│   └── Shard test suites across multiple runners\n├── Optimize the test suite\n│   └── Remove slow tests from the critical path, run them on a schedule instead\n└── Use larger runners\n    └── GitHub-hosted larger runners or self-hosted for CPU-heavy builds\n```\n\n**Example: caching and parallelism**\n```yaml\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with: { node-version: '22', cache: 'npm' }\n      - run: npm ci\n      - run: npm run lint\n\n  typecheck:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with: { node-version: '22', cache: 'npm' }\n      - run: npm ci\n      - run: npx tsc --noEmit\n\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with: { node-version: '22', cache: 'npm' }\n      - run: npm ci\n      - run: npm test -- --coverage\n```\n\n## Common Rationalizations\n\n| Rationalization | Reality |\n|---|---|\n| \"CI is too slow\" | Optimize the pipeline (see CI Optimization below), don't skip it. A 5-minute pipeline prevents hours of debugging. |\n| \"This change is trivial, skip CI\" | Trivial changes break builds. CI is fast for trivial changes anyway. |\n| \"The test is flaky, just re-run\" | Flaky tests mask real bugs and waste everyone's time. Fix the flakiness. |\n| \"We'll add CI later\" | Projects without CI accumulate broken states. Set it up on day one. |\n| \"Manual testing is enough\" | Manual testing doesn't scale and isn't repeatable. Automate what you can. |\n\n## Red Flags\n\n- No CI pipeline in the project\n- CI failures ignored or silenced\n- Tests disabled in CI to make the pipeline pass\n- Production deploys without staging verification\n- No rollback mechanism\n- Secrets stored in code or CI config files (not secrets manager)\n- Long CI times with no optimization effort\n\n## Verification\n\nAfter setting up or modifying CI:\n\n- [ ] All quality gates are present (lint, types, tests, build, audit)\n- [ ] Pipeline runs on every PR and push to main\n- [ ] Failures block merge (branch protection configured)\n- [ ] CI results feed back into the development loop\n- [ ] Secrets are stored in the secrets manager, not in code\n- [ ] Deployment has a rollback mechanism\n- [ ] Pipeline runs in under 10 minutes for the test suite","tags":["and","automation","agent","skills","addyosmani"],"capabilities":["skill","source-addyosmani","category-agent-skills"],"categories":["agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/addyosmani/agent-skills/ci-cd-and-automation","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"install_from":"skills.sh"}},"qualityScore":"0.300","qualityRationale":"deterministic score 0.30 from registry signals: · indexed on skills.sh · published under addyosmani/agent-skills","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T10:40:33.396Z","embedding":null,"createdAt":"2026-04-18T20:32:29.227Z","updatedAt":"2026-04-22T10:40:33.396Z","lastSeenAt":"2026-04-22T10:40:33.396Z","tsv":"'1':711,972 '10':715,1009,1405 '100':717 '10s':364 '15':796 '16':338 '2':904 '22':278,384,478,1133,1161,1189 '3':112 '30':121 '5':372,919,1219 '5432':353,354 '5432/testdb':407,425 '5s':368 'a/b':719 'accident':449 'accumul':957,1272 'across':1072 'action':242 'actions/cache':1024 'actions/checkout':269,375,469,654,1124,1152,1180 'actions/setup-node':272,378,472,1127,1155,1183 'actions/upload-artifact':510 'ad':142 'add':1266 'addyosmani':9 'agent':5,45,528,535,553,573,583,593,604,614 'ai':534 'analysi':86 'anyway':1242 'api/db':195 'appli':1011 'approv':973,1000 'assum':960 'audit':203,205,314,317,319,1362 'audit-level':318 'auto':782,790,993 'auto-merg':992 'autom':4,12,14,145,155,896,1294 'automat':1002 'back':526,696,1381 'basic':244 'batch':99 'becom':763 'behavior':722 'behind':678 'beyond':897 'block':1373 'branch':254,257,984,1375 'break':933,951,1234 'broken':954,1273 'bug':68,76,1255 'build':30,124,189,192,307,311,444,496,500,612,920,932,935,955,1042,1068,1108,1235,1361 'bundl':207 'bundles':209 'cach':279,385,479,1021,1029,1110,1134,1162,1190 'canari':706,750 'catch':41,58 'category-agent-skills' 'caught':69,77 'caus':949 'cd':2 'chang':20,55,113,152,165,948,1050,1227,1233,1241 'check':28,83,146,176,181,210,295,615,967,978,997 'checkout':737 'chromium':494 'ci':1,140,158,245,250,286,345,389,401,419,430,483,524,532,541,543,555,576,870,884,894,898,928,979,1003,1019,1138,1166,1194,1203,1211,1231,1236,1267,1271,1301,1306,1314,1333,1340,1352,1378 'ci-on':429 'ci/cd':10,31 'clean':802 'cleanup':768 'cmd':358 'code':235,684,705,758,1331,1395 'commit':590,854,860,864 'common':1199 'compar':721 'confid':125 'config':616,1334 'configur':147,243,1377 'consist':51 'context':456 'cop':921,936 'copi':545 'cost':72,80 'coverag':305,1198 'cpu':1106 'cpu-heavi':1105 'creat':746,772 'credenti':438,453 'critic':1084 'databas':323,399,417,433 'date':769 'day':1279 'db':341,350,404,422 'dead':757 'debt':765 'debug':117,157,607,1225 'debugging-and-error-recoveri':606 'decoupl':669 'dep':493 'depend':283,618,1022 'dependabot':899 'deploy':110,148,397,619,622,628,633,639,657,670,673,781,786,807,840,842,881,1321,1396 'deploy-preview':638 'descript':822 'design':923 'detect':800 'develop':857,862,1384 'directori':910 'disabl':226,699,1312 'dispatch':819 'doc':1063 'docs-on':1062 'doesn':1287 'done':803 'e.g':1058 'e2e':198,457,460,503,1060 'earli':61,691 'easier':115 'ecosystem':908 'effort':1345 'els':962 'enabl':686,692,709,747 'enforc':34 'enough':1284 'env':339,398,416,858 'env.example':853 'env.test':863 'environ':851,866 'error':560,563,592,596,609,613,795,799 'eslint':177 'even':427 'everi':37,53,164,623,806,1366 'everyon':959,1258 'exampl':1109 'exceed':1008 'fail':221,232,542,544,557 'failur':159,513,525,547,582,603,1307,1372 'fast':1238 'faster':95 'featur':665,667,677,708,727,730 'featureflags.isenabled':734 'feed':523,549,1380 'feedback':538 'file':1335 'filter':1053 'fix':222,233,564,574,588,599,941,964,1261 'flag':666,668,679,701,731,744,755,759,1299 'flaki':1246,1251,1263 'flow':738 'follow':605 'forc':988 'force-push':987 'forev':762 'frequent':102,122 'full':751 'gate':16,162,169,215,1355 'get':625 'github':241,435,874,1096 'github-host':1095 'github.event':648 'github/dependabot.yml':902 'github/workflows/ci.yml':248 'goe':166 'good':445 'green':929 'habit':446 'hardcod':441 'health':357,362,366,370 'health-cmd':356 'health-interv':361 'health-retri':369 'health-timeout':365 'heavi':1107 'high':321 'host':1097,1103 'hour':81,1223 'human':43 'ignor':1308 'imag':336 'impact':1017 'incomplet':674 'increas':107 'input':820 'inputs.version':850 'instal':282,485,490 'instead':702,1091 'integr':194,324,327,409,415 'interv':363,912 'isn':1291 'isreadi':360 'issu':566 'jest/vitest':187 'job':259,829,938,1035,1046,1057,1114 'keep':927 'key':579 'larger':1093,1098 'later':1268 'latest':266,333,466,646,836,1121,1149,1177 'least':971 'left':57 'level':320 'lifecycl':745 'limit':918 'lint':26,71,175,220,223,288,292,581,587,1039,1115,1142,1358 'live':761 'll':1265 'local':569,861 'localhost':406,424 'locat':597 'long':1339 'loop':539,1385 'main':255,258,690,779,991,1371 'make':1316 'manag':852,1338,1392 'manual':630,783,787,812,1281,1285 'mask':1253 'matrix':1067 'mechan':35,1327,1400 'merg':171,688,777,975,983,994,1001,1374 'migrat':392,396 'minut':73,797,1010,1220,1406 'miss':46 'modifi':144,1351 'modul':1033 'monitor':793 'move':82 'multipl':1073 'must':980 'name':249,281,287,293,300,306,312,390,408,484,495,501,515,649,656,815,838 'never':886 'new':137,707,736 'new-checkout-flow':735 'node':276,382,476,1028,1032,1131,1159,1187 'node-vers':275,381,475,1130,1158,1186 'noemit':183,299,1170 'note':426 'npm':190,204,280,285,290,303,309,316,386,388,412,480,482,498,585,909,1135,1137,1140,1163,1165,1191,1193,1196 'npx':297,394,488,506,660,847,1168 'one':119,1280 'open':174,915 'open-pull-requests-limit':914 'optim':1004,1075,1207,1212,1344 'option':199,355,1030 'order':1015 'output':548 'overview':13 'packag':907 'package-ecosystem':906 'parallel':1037,1045,1112 'pass':24,179,184,188,193,197,201,206,981,998,1319 'password':348,351,405,423 'past':561 'path':519,1052,1085 'pattern':580,732 'person':946 'pg':359 'pipelin':64,141,149,163,246,556,1007,1020,1209,1221,1302,1318,1363,1401 'plan':805 'platform':882 'playwright':486,489,507,517,521 'playwright-report':516,520 'playwright/cypress':200 'port':352 'possibl':66 'postgr':335,337,340,343,347 'power':530 'pr':624,636,776,966,1367 'present':1357 'prettier':178 'prevent':448,953,1222 'preview':621,627,634,640,658 'previous':845 'prisma':395 'problem':59 'process':129 'product':22,79,94,785,877,888,1320 'project':138,1269,1305 'protect':985,1376 'prs':1065 'pull':172,252,650,916 'push':256,571,575,989,1369 'qualiti':15,161,260,1354 'rather':439 'ration':1200,1201 're':1249 're-run':1248 'reach':21 'read':594 'readi':211,694 'real':868,1254 'realiti':1202 'recoveri':610 'red':1298 'redeploy':698 'reduc':104 'releas':103,123,128,672 'remov':753,1079 'renderlegacycheckout':743 'rendernewcheckout':741 'renov':900 'repeat':1293 'report':518,522 'request':173,253,651,917 'requir':827,968,976 'respons':925 'result':1379 'retri':371 'return':740,742 'reus':450 'revers':810 'revert':704,943 'review':213,969 'risk':105 'riski':676 'role':922 'roll':695 'rollback':801,804,813,816,825,830,839,849,1326,1399 'rollout':752,775 'rule':228 'run':191,262,284,289,291,296,302,308,310,315,329,387,391,393,411,413,462,481,487,497,499,502,505,577,584,586,642,659,718,832,841,1034,1048,1086,1117,1136,1139,1141,1145,1164,1167,1173,1192,1195,1250,1364,1402 'runner':1074,1094,1099 'runs-on':261,328,461,641,831,1116,1144,1172 'safer':97 'scale':1289 'schedul':911,1090 'secret':436,869,871,875,878,889,892,1328,1337,1386,1391 'secrets.ci':349,403,421 'secrets.vercel':663 'secur':202,313 'see':1210 'self':1102 'self-host':1101 'separ':891,1044 'servic':334 'set':134,766,1275,1348 'setup':1027 'setup-nod':1026 'shard':1069 'shift':56 'ship':683 'silenc':1310 'simpl':729 'singl':54 'size':208 'skill':6,7,39,611 'skip':218,238,1055,1059,1216,1230 'slow':1018,1080,1206 'smaller':98 'someon':924,961 'source-addyosmani' 'specif':562 'specifi':844 'split':1038 'stage':91,92,774,780,792,1323 'state':1274 'static':85 'status':977 'step':267,373,467,652,837,1122,1150,1178 'store':872,879,1329,1388 'strategi':620,1013 'suit':1071,1078,1410 'technic':764 'templat':855 'test':25,88,89,186,196,231,240,301,304,325,410,414,432,452,458,504,508,602,631,720,749,865,895,1041,1070,1077,1081,1171,1197,1244,1252,1282,1286,1311,1360,1409 'testdb':342 'time':1260,1341 'timeout':367 'token':662,664 'trigger':154,788 'trivial':1229,1232,1240 'true':828 'tsc':182,298,1169 'type':27,180,294,591,601,1359 'typecheck':1040,1143 'typescript':728 'ubuntu':265,332,465,645,835,1120,1148,1176 'ubuntu-latest':264,331,464,644,834,1119,1147,1175 'unit':185 'unrel':1056 'updat':905 'upstream':84 'url':400,418 'use':133,268,271,374,377,434,468,471,509,653,890,1023,1051,1066,1092,1123,1126,1151,1154,1179,1182 'user':344,346,402,420,713 'userid':739 'v4':270,273,376,379,470,473,511,655,1125,1128,1153,1156,1181,1184 'valu':442 'vault':876,883 'vercel':661,848 'vercel/netlify/etc':637 'verif':156,784,1324,1346 'verifi':568 'version':277,383,477,821,823,846,903,1132,1160,1188 'wast':1257 'week':913 'whose':947 'window':798 'with-dep':491 'without':23,685,697,725,1270,1322 'workflow':814,818 'yaml':247,326,459,632,811,901,1113","prices":[{"id":"13736c39-450b-4a6b-8755-c7df74db4f1f","listingId":"249715cd-823e-4a71-93ad-5415a74d2417","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"addyosmani","category":"agent-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:32:29.227Z"}],"sources":[{"listingId":"249715cd-823e-4a71-93ad-5415a74d2417","source":"github","sourceId":"addyosmani/agent-skills/ci-cd-and-automation","sourceUrl":"https://github.com/addyosmani/agent-skills/tree/main/skills/ci-cd-and-automation","isPrimary":false,"firstSeenAt":"2026-04-18T21:52:55.126Z","lastSeenAt":"2026-04-22T06:52:41.842Z"},{"listingId":"249715cd-823e-4a71-93ad-5415a74d2417","source":"skills_sh","sourceId":"addyosmani/agent-skills/ci-cd-and-automation","sourceUrl":"https://skills.sh/addyosmani/agent-skills/ci-cd-and-automation","isPrimary":true,"firstSeenAt":"2026-04-18T20:32:29.227Z","lastSeenAt":"2026-04-22T10:40:33.396Z"}],"details":{"listingId":"249715cd-823e-4a71-93ad-5415a74d2417","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"addyosmani","slug":"ci-cd-and-automation","source":"skills_sh","category":"agent-skills","skills_sh_url":"https://skills.sh/addyosmani/agent-skills/ci-cd-and-automation"},"updatedAt":"2026-04-22T10:40:33.396Z"}}