This is a personal work in progress. Keep in mind your suggestions are welcome! :)
These workflows are highly opinionated kubectl-apply or helm-upgrade pipelines.
- Versioning with Semantic-Release
- Linter:
- Hadolint for Dockerfiles
- ESLint for Javascript
- PyLint for Python
- Static analysis:
This pipeline assumes you have just 4
types of repositories:
Name | Short | Description | Result |
---|---|---|---|
Web Application | app | Front-end application with internet-facing ingress | language-based pod |
Mobile Application | mob | Mobile application | apk |
Service | svc | Microservice that may - or may not - have ingress | nginx-based pod |
Infrastructure as Code | iac | Code that generates cloud infrastructure | - |
Those repositories must obey a name pattern.
{ecosystem}-{type}-{name/client/integration}
Examples:
ff-svc-clients
: microservice that manages clients' dataff-app-budget
: application that organizes the company financesff-mob-auth
: 2FA mobile applicationff-iac-aws
: infra as code to manage the aws environment
Checkout the test repositories:
Type | Solution | Repository | Pipeline | Deploy |
---|---|---|---|---|
app | filipeforattini/ff-app-react | |||
app | filipeforattini/ff-app-vue | |||
svc | filipeforattini/ff-svc-express | |||
svc | filipeforattini/ff-svc-fastapi | |||
svc | filipeforattini/ff-svc-flask | |||
svc | filipeforattini/ff-svc-moleculer | |||
svc | filipeforattini/ff-svc-nestjs | |||
svc | filipeforattini/ff-svc-nextjs |
Name | Short | Description |
---|---|---|
Development | dev | Env for you and your team to test and explore |
Staging | stg | Stable env for code shipping |
Sandbox | sbx | Production-like env for external developers |
Production | prd | Where the magic happens |
Disaster Recovery | dry | Production copy |
flowchart
start[Start]
analysis[Analysis]
node-test[Node Tests]
python-test[Python Tests]
static-analysis[Static Analysis]
start --- |action/manual| analysis
start --- |action/github| analysis
analysis --- |event/push| static-analysis
static-analysis --- |lang/javascript| node-test
static-analysis --- |lang/python| python-test
static-analysis --- |lang/go| go-test
subgraph node:
node-test --- node-release
node-release --- node-trigger
end
subgraph python:
python-test --- python-release
python-release --- python-trigger
end
subgraph go:
go-test --- go-release
go-release --- go-trigger
end
node-trigger --- |deployment/dev| finish
python-trigger --- |deployment/dev| finish
go-trigger --- |deployment/dev| finish
analysis --- |event/pull-request| static-analysis
trigger --- |env/xxx| finish
analysis --- |event/deployment| build
build --- |env/dev| env-dev
build --- |env/stg| env-stg
build --- |env/prd| env-prd
subgraph dev:
env-dev --- |app.dev.domain.io| DEV
env-dev --- |app-commit.dev.domain.io| DEV
end
subgraph stg:
env-stg --- |app.stg.domain.io| STG
end
subgraph prd:
env-prd --- |app.prd.domain.io| PRD
end
├─ .github
│ └─ workflows
│ │ └─ pipeline.yml
│ └─ dependabot.yml
├─ manifests
│ ├─ configs
│ │ └─ dev.env
│ ├─ dependencies
│ │ └─ dev.yml
│ ├─ secrets
│ │ └─ dev.gpg
│ ├─ k8s.yml
│ └─ helm.yml
├─ build
│ // distibuition version of our code
└─ src
// our code goes here
Add this pipeline to your repository:
name: pipeline
on:
push:
deployment:
release:
types: [created]
pull_request:
types: [opened, reopened]
jobs:
APP:
uses: filipeforattini/ff-iac-github-actions/.github/workflows/app.yml@main
secrets: inherit
with:
mainBranch: main
platforms: linux/amd64,linux/arm64
staticAnalysis: false
containerRegistry: ghcr.io
nodeMatrix: '[17]'
environmentsAsNamespaces: true
Name | Default | Description |
---|---|---|
containerRegistry | ghcr.io | Container registry host that you will use |
environmentsASnamespaces | false |
Configure your
Organizes the whole workflow jobs' inputs.
- Checkout your code and few tools from this repo.
- Configure repository environments.
- List all environments
- for (env in [dev, stg, sbx, prd, dry]): 1.
- List all environments
- Runs scrappers to extract information from your repository and environment keys.
- (TODO) Updates repository configs
- (TODO) Create environments
- Define which path should this build go.
- if [ event_name = push ]
- Build your repository. Supported: nodejs, python
- Checkout your code and few tools from this repo again.
- Define few variables for your build
- Install version
- Loads cache that matches with your repository organization
- Install dependencies
- Runs few scripts
- Generates a .dockerignore, if there isn't one
- Generates a dockerfile, if there isn't one
- Setups docker builder
- Log-in into your Container Registry
- Builds and push the container
- Deploy your container into your DEV environment
- Build your repository. Supported: nodejs, python
- if [ event_name = pull_request ]
- Code quality check
- Checkout your code and few tools from this repo again.
- Define few variables for your build
- Team approval
- Code quality check
git commit -m "action(scope): subject"
Where the actions:
feat
: new feature for the user, not a new feature for the build scriptfix
: bug fix for the user, not a fix for a build scriptdocs
: documentation changesstyle
: formatting, lack of semicolons, etc; no changes to the production coderefactor
: refactoring the production code, for example. renaming a variabletest
: adding missing tests, refactoring tests; no changes to the production codechore
:updating grunted tasks, etc; no changes to the production code
Adds BREAKING CHANGE
in the commit message and it will generate a new major version.
gpg -v \
--symmetric \
--cipher-algo AES256 \
--output ./manifests/secrets/dev.gpg \
./manifests/secrets/dev.env
Thanks to:
- https://evilmartians.com/chronicles/build-images-on-github-actions-with-docker-layer-caching
- https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/
This ecosystem generates few data per second as samples for our apis.
In this implementation, each service has its own resources.
flowchart
https---ingress
subgraph k8s
ingress---|ff-svc-nestjs.dev.forattini.app|nestjs
ingress---|ff-svc-nextjs.dev.forattini.app|nextjs
ingress---|ff-svc-fastapi.dev.forattini.app|fastapi
ingress---|ff-svc-moleculer.dev.forattini.app|moleculer
subgraph ff-svc-nextjs
nextjs---rabbitmq-nextjs[rabbit]
end
subgraph ff-svc-moleculer
moleculer---postgres-moleculer[postgres]
moleculer---mysql-moleculer[mysql]
moleculer---redis-moleculer[redis]
moleculer---rabbitmq-moleculer[rabbit]
moleculer---etcd-moleculer[etcd]
moleculer---nats-moleculer[nats]
moleculer---rabbitmq-nextjs
end
subgraph ff-svc-fastapi
fastapi---postgres-fastapi[postgres]
fastapi---rabbitmq-fastapi[rabbit]
fastapi---rabbitmq-nextjs
end
subgraph ff-svc-nestjs
nestjs---postgres-nestjs[postgres]
nestjs---rabbitmq-nestjs[rabbitmq]
nestjs---rabbitmq-nextjs
end
end
In this implementation, all services connects to a shared resource.
flowchart
https---ingress
subgraph k8s
ingress---|ff-svc-nestjs.dev.forattini.app|nestjs
ingress---|ff-svc-nextjs.dev.forattini.app|nextjs
ingress---|ff-svc-fastapi.dev.forattini.app|fastapi
ingress---|ff-svc-moleculer.dev.forattini.app|moleculer
subgraph ff-svc-nextjs
nextjs---rabbitmq-nextjs[rabbit]
nextjs---postgres-nextjs[postgres]
nextjs---mysql-nextjs[mysql]
nextjs---redis-nextjs[mysql]
etcd-nextjs[etcd]
nats-nextjs[nats]
end
subgraph ff-svc-moleculer
moleculer---postgres-nextjs
moleculer---mysql-nextjs
moleculer---redis-nextjs
moleculer---rabbitmq-nextjs
moleculer---etcd-nextjs
moleculer---nats-nextjs
end
subgraph ff-svc-fastapi
fastapi---postgres-nextjs[postgres]
fastapi---rabbitmq-nextjs[rabbit]
end
subgraph ff-svc-nestjs
nestjs---postgres-nextjs[postgres]
nestjs---rabbitmq-nextjs[rabbitmq]
end
end