{"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6","forks_url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/forks","commits_url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/commits","id":"ea43fe9eab2ab02db863a3a0686ee5b6","node_id":"MDQ6R2lzdGVhNDNmZTllYWIyYWIwMmRiODYzYTNhMDY4NmVlNWI2","git_pull_url":"https://gist.github.com/ea43fe9eab2ab02db863a3a0686ee5b6.git","git_push_url":"https://gist.github.com/ea43fe9eab2ab02db863a3a0686ee5b6.git","html_url":"https://gist.github.com/michaellihs/ea43fe9eab2ab02db863a3a0686ee5b6","files":{"patterns-antipatterns-cicd.md":{"filename":"patterns-antipatterns-cicd.md","type":"text/markdown","language":"Markdown","raw_url":"https://gist.githubusercontent.com/michaellihs/ea43fe9eab2ab02db863a3a0686ee5b6/raw/bac498be124e7937c4da9b2eb0e6f0840ef0059f/patterns-antipatterns-cicd.md","size":3567,"truncated":false,"content":"# Patterns and Anti-Patterns for CI/CD\n\n## The Developer Experience\n\n* The developer journey\n  * visualize devs' emotions during their workflow\n* make sure to provide a good experience for your devs as well (not only for customers and users)\n\n\n## Working Models\n\n* Pairing vs Review\n* Good / bad User Stories\n\n\n## Source Code Management\n\n* Feature branches vs. trunk based development\n* embed trunk-based dev in your SW workflow\n\n\n## Versions & Releases\n\n* Semantic Versioning\n* Automating the versioning process?\n* Traceability\n\n\n## Dev / Prod Parity\n\n* Running stuff on dev workstations vs running stuff in CI/CD vs running stuff in Production\n* Docker to the rescue\n  * spin up all the things locally\n  * provide containerized dev envs\n  \n\n## The `do` script\n\n* Automate all the things\n* Use the same scripts in dev and in CI/CD\n* Provide a inspiring developer experience\n* e.g.\n  * build locally (in a container)\n  * run locally (in a container)\n  * run tests\n  * start dependencies (database...)\n* run your pipeline logic during development, too\n\n\n## Pipelines that don't suck\n\nWhat makes a good pipeline -> link to Mario's talk\n\n* the pipeline is code\n  * it's declarative\n  * it's versioned with your code\n* the pipeline is visual\n* it scales\n  * with project size\n  * with number of builds\n  * with number of repositories\n* it is not some **snowflake configuration** in a clicking-only UI\n* locally executable\n  * see `do` script\n* it **should not** be the super-complicated unicorn script that no developer ever wants to touch\n\n\n## Good Conventions\n\n* Good READMEs\n  * same structure\n  * kept up-to-date\n* have similar pipelines for similar projects\n  * makes it easier for onboarding\n  * devs are less scary to touch / repair things, because they know it\n  \n  \n## If possible: use SaaS solutions\n\n* spend your time on the business value, not on fixing your tools\n  * a CI/CD toolchain itself brings no business value\n* easily speed up things by adding more powerful build agents (Cloud...)\n* takes care of the ugly stuff\n  * build agents for different architectures\n  * cleaning up\n  * resource management\n  \n  \n## CI/CD and security\n\n* credentials management\n  * inject at runtime (e.g. Vault)\n* security scans\n  * Docker images\n  * libraries and dependencies\n* securing the delivery process itself\n  * again: Docker to the rescuee: signing images, trusted registries...\n  \n  \n## Autonomy over avoiding redundancy\n\n* Find a good balance between reducing redundancy and keeping teams autonomous\n* Strive for small components with less blast radius but faster release cycles\n* avoid blocking of releases due to waiting on other people's code\n\n\n## Design for Continuous Delivery\n\n* Idempotence (re-running stuff should do no harm)\n* Avoid any manual intervention\n  * think about this right from the design phase\n* Design for blue / green deployments\n  * provide health endpoint\n  \n## CI/CD as shared responisibility\n\n* Antip-Pattern: \"the one person taking care about the pipeline in the team\"\n* involve everybody, make the pipeline a \"shared responsibility\"\n* bring it into tech huddles, make sure everyone in the team understands how things work\n* involve client / PO, make sure they understand the importance of time spent on CI/CD and how this improves the team performance\n\n  \n## Trunk-based development\n\n* [Kief's Blog Post](https://infrastructure-as-code.com/book/2021/01/02/pull-requests.html)\n\n## Credentials Handling / Security\n\n* logging of passwords\n* accessing credentials / vaults\n\n## Shell script issues\n\n* about `exit 0`\n* `set -... pipefail`\n","encoding":"utf-8"}},"public":true,"created_at":"2020-02-24T09:06:44Z","updated_at":"2024-01-07T10:12:03Z","description":"Patterns and Anti-Patterns for CI/CD","comments":0,"user":null,"comments_enabled":true,"comments_url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/comments","owner":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"forks":[],"history":[{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"eb1fb21875bb9701c33b43476fe7c40fe7128683","committed_at":"2021-01-28T15:42:05Z","change_status":{"total":12,"additions":11,"deletions":1},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/eb1fb21875bb9701c33b43476fe7c40fe7128683"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"0806cc8fd48b8e73f9f817c24a329cc2aaa4b809","committed_at":"2021-01-26T09:17:26Z","change_status":{"total":9,"additions":9,"deletions":0},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/0806cc8fd48b8e73f9f817c24a329cc2aaa4b809"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"a63388aede00c622e64a9db8858eb3eb70c36108","committed_at":"2021-01-05T14:42:46Z","change_status":{"total":6,"additions":5,"deletions":1},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/a63388aede00c622e64a9db8858eb3eb70c36108"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"e7ef29b2629efc54bb7f0f8b259ffea00e06bdeb","committed_at":"2020-04-08T11:09:03Z","change_status":{"total":5,"additions":4,"deletions":1},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/e7ef29b2629efc54bb7f0f8b259ffea00e06bdeb"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"d617b4613d66abf97369a2d81555660b3850dd62","committed_at":"2020-04-08T09:10:54Z","change_status":{"total":9,"additions":8,"deletions":1},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/d617b4613d66abf97369a2d81555660b3850dd62"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"aca53389576ce11230e86accd8ed2d7f741f29b0","committed_at":"2020-03-06T19:28:19Z","change_status":{"total":8,"additions":7,"deletions":1},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/aca53389576ce11230e86accd8ed2d7f741f29b0"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"3f53bd2336944bce3af18fc04b3bbb5fdf21e8b3","committed_at":"2020-03-06T19:18:40Z","change_status":{"total":1,"additions":1,"deletions":0},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/3f53bd2336944bce3af18fc04b3bbb5fdf21e8b3"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"d13662395599e49bb3dfe367ce5714452c0f74b7","committed_at":"2020-02-24T09:06:44Z","change_status":{"total":95,"additions":95,"deletions":0},"url":"https://api.github.com/gists/ea43fe9eab2ab02db863a3a0686ee5b6/d13662395599e49bb3dfe367ce5714452c0f74b7"}],"truncated":false}