CI/CD - Lint - Checks
Continuous Integration (CI):
Continuous integration is a software development practice where developers regularly merge their code changes into a central repository, after which automated builds and tests are run. The key goals of CI are to detect integration bugs as quickly as possible, improve software quality, and reduce the time taken to validate and release new updates.
Some key aspects of CI include:
- Developers committing code to a shared repository (e.g. Git) several times a day
- Each commit triggers an automated build and test process
- Fast feedback on build or test failures
- Maintaining a codebase that is always ready for release
Continuous Delivery (CD):
Continuous delivery is a software development practice where code changes are automatically built, tested, and prepared for release to production. It expands upon continuous integration by deploying all code changes to a testing environment and/or a production environment after the build stage.
Key aspects of CD:
- Automated release process that takes code from version control to production
- Deployment happens automatically after build and test steps are successful
- Manual intervention removed from process as much as possible
- Ability to release new changes fast and safely
- Maintaining deployable code at all times
- The main difference between continuous integration and continuous delivery is that CI focuses on the build/test stage while CD looks to automate the release of changes to users. CI is centered on developer workflow, while CD involves automating production deployment.
Embedded content: https://docs.google.com/presentation/d/1M0JsrNRRbt1Z4uO3LVW9-q1tAx8N_k3iK-jLxfDi_HM/edit?usp=sharing
Tools for CI/CD
Github Actions
Github Actions is a CI/CD platform built into Github that allows you to automate software development workflows. Some key features:
- YAML-based workflow definitions
- Supports all major languages and frameworks
- Integrates tightly with Github pull requests and branches
- Large library of reusable actions
- Flexible execution environment with Linux, Windows, and MacOS runners
Running automated tests
Deploying to S3
Drone
Drone is an open source CI/CD platform that integrates with Github and other repositories. Key features:
- YAML-based pipelines
- Built-in cache and artifacts support
- Supports Docker, Kubernetes, and other environments
- Easy parallelization across pipelines
- Integrations with cloud providers
Benefits of Linting in CI/CD Pipelines
- Catch issues early
- Enforce code quality and conventions
- Improve productivity
- Prevent bugs and errors
- Facilitate code reviews
- Complement testing Here are some improved topics with descriptions and examples of linting tools:
Types of Linting Tools and Checks
Code Style
Checks for consistent code style and formatting.
Examples:
-
Prettier - An opinionated code formatter that enforces consistent style.
-
ESLint - Highly configurable linter that can enforce code style rules.
Code Quality
Checks code for potential quality and maintainability issues.
Examples:
-
SonarQube - Code quality platform that can analyze technical debt, bugs, vulnerabilities and more.
-
Code Climate - Automated code review with quality checks and metrics.
Error Proneness
Checks code for common bugs and mistakes.
Examples:
-
ESLint - Rules like no-unused-vars can catch common bugs.
-
Pylint - Checks Python code for errors, bugs, stylistic errors and more.
Security Issues
Checks for security vulnerabilities and best practices.
Examples:
-
Bandit - Security linter for Python.
-
Brakeman - Scans Ruby on Rails apps for security vulnerabilities.
Integrate ESLint and Prettier
Here is a concise guide for integrating ESLint and Prettier:
Integrate ESLint and Prettier
-
Install dependencies:
npm install eslint eslint-config-prettier prettier --save-dev
-
Run eslint --init and select:
- To check syntax and find problems
- JavaScript modules
- None of these
-
In .eslintrc.json, extend eslint:recommended and prettier:
{ "extends": ["eslint:recommended", "prettier"] }
-
Create .prettierrc.json:
{ "trailingComma": "es5", "tabWidth": 2, "semi": false }
-
Add scripts in package.json:
{ "scripts": { "lint": "eslint .", "format": "prettier --write ." } }
Now you can lint with
npm run lint
and format with
npm run format
Using Git Hooks to trigger Lint and Tests
Git hooks are scripts that run automatically when certain actions occur in a Git repository. They allow you to trigger custom scripts during the Git workflow.
Git hooks are located in the .git/hooks directory of a repository. The scripts can be in any language (Bash, Python, Ruby, etc). Some common hooks you can implement include:
- pre-commit: Before a commit is created
- commit-msg: Validate commit message
- post-commit: After a commit is created
- pre-push: Before code is pushed
- post-merge: After a branch is merged
To enable a hook, you just need to place an executable script in the hooks directory with the naming convention like pre-commit. But you can change the default folder from .git/hooks to another one with the following script:
"preinstall": "command -v git >/dev/null 2>&1 && git config core.hooksPath githooks || echo 'Skip preinstall, git not found'",
You can also use Husky package .
Deployment Strategies
Reckless Deployment: As the name suggests, this strategy is the most reckless, but also the easiest of all. Its goal is simply to destroy all the logical content located on the server and replace it with the new version. It's interesting not to discard this strategy; however, it is recommended only for small developments with testing purposes.
Rolling Upgrade = I_O
This strategy consists of updating the code gradually until all instances have the new version. With this, we can measure the impacts more subtly and advance according to the possibilities. For this to be possible, it is essential that the health of the system is monitored.
Blue/ Green
In the Blue/Green strategy, you basically generate a completely independent new version of the old version and, once validated, route users to the new version. In contrast to Reckless Deployment, this is the safest strategy. To ensure everything works well, we don't touch the current production version. Instead, we provision a copy and, after the development is completed and validated, in the time that is necessary, we activate the new version. Depending on your strategy, you can do this for all users at once (cut-off or cut-over) or make the version available to users gradually.
Canary = PWM IOIOIOIOIO
Here you deploy the new version in Production, still with the old version running, however, you control who will have access to the update. Strategy used by Facebook with its employees and, later, with common users who make themselves available to receive experimental updates (the Demos). This is one of the most advanced, if not the most advanced, of the strategies mentioned so far. For this to be possible, it is essential that you have a balancing/proxy layer. It can be compared to Blue/Green due to the proximity of the way of working, with the addition of this intelligent routing that allows a balance/availability for certain users. It is worth noting that the more granular your control power is, the more advanced your Canary implementation is and, consequently, more complex.