versions
is a single binary that hold both frontend UI and API that permit to centralize all your applications versions deployed in order to know when it has been deployed and his content.
Workload
: it mean which team is related to this deployment.
Platform
: release to which platform your application has been deployed like development, staging, preproduction or production.
Environment
: on each platform, multiple environment can be deployed like development or integration.
You need to define OS environment variables like so:
# for mysql
export SQL_DRIVER=mysql
export DB_URI="USERNAME:PASSWORD@tcp(HOST:PORT)/DB_NAME?charset=utf8&autocommit=true&multiStatements=true&maxAllowedPacket=0&interpolateParams=true&parseTime=true"
# for postgres
export SQL_DRIVER=postgres
export DB_URI="postgres://USERNAME:PASSWORD@HOST:PORT/DB_NAME?sslmode=disable"
# If you want to enable a redis
export REDIS_ENABLED=true
export REDIS_URI=redis://:xxxxx@host:port/db
# or
export REDIS_ENABLED=true
export REDIS_URI=redis://:xxxxx@host:port
SQL_DRIVER can only be mysql
or postgres
At startup, the DB initialization or migration will be handle.
Here are the supported versions:
- postgres 10 and above
- mariadb 10.x and above
- mysql 5.7 and above
Port number can be change:
export APP_PORT=8080
Unit testing are covered.
go test -v ./... -coverprofile=coverage.out
# go tool cover -html=coverage.out
# go tool cover -func=coverage.out
For POST request, both content-type
# post requests with json
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.0.0","workload": "teamX", "environment":"production", "platform": "production", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "ongoing"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.1.0","workload": "teamX", "environment":"production", "platform": "production", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.3.0","workload": "teamX", "environment":"dev", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "failed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.2.0","workload": "teamX", "environment":"integration", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "ongoing"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.0.0","workload": "teamY", "environment":"production", "platform": "production", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.1.0","workload": "teamY", "environment":"production", "platform": "production", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.3.0","workload": "teamY", "environment":"dev", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "ongoing"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.2.0","workload": "teamY", "environment":"integration", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.0.0","workload": "teamZ", "environment":"production", "platform": "production", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.1.0","workload": "teamZ", "environment":"production", "platform": "production", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "ongoing"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.3.0","workload": "teamZ", "environment":"dev", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.2.0","workload": "teamZ", "environment":"integration", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "0.2.0","workload": "teamZ", "environment":"test", "platform": "development", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
curl -XPOST 0:8080/api/v1/create -H 'Content-type: application/json' -d '{"version": "1.1.0","workload": "teamZ", "environment":"preproduction", "platform": "preproduction", "changelogURL": "https://jsonplaceholder.typicode.com/", "raw": "{\"a\":\"b\"}", "status": "deployed"}'
# post requests with form format mode
curl -XPOST 0:8080/api/v1/create -d 'version=1.1.0&workload=teamX&environment=production&platform=production&changelogURL=https://jsonplaceholder.typicode.com/&raw=rawContent&status=ongoing'
curl -XPOST 0:8080/api/v1/create -d 'version=1.3.0&workload=teamX&environment=production&platform=production&changelogURL=https://jsonplaceholder.typicode.com/&raw=rawContent&status=deployed'
curl -XPOST 0:8080/api/v1/create -d 'version=1.2.0&workload=teamX&environment=production&platform=production&changelogURL=https://jsonplaceholder.typicode.com/&raw=rawContent&status=failed'
Each POST
return the id of the deployment like so {"versionId":14}
.
To update the status of the deployment:
curl -XPOST 0:8080/api/v1/update/status -H 'Content-type: application/json' -d '{"versionId": "14","status": "deployed"}'
Here is an example of DB content:
+-------------+----------+---------------+---------------+---------+---------------------------------------+---------------+----------+---------------------+
| versions_id | workload | platform | environment | version | changelog_url | raw | status | date |
+-------------+----------+---------------+---------------+---------+---------------------------------------+---------------+----------+---------------------+
| 1 | teamX | production | production | 1.0.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | ongoing | 2020-12-02 19:58:10 |
| 2 | teamX | production | production | 1.1.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 3 | teamX | development | dev | 1.3.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | failed | 2020-12-02 19:58:10 |
| 4 | teamX | development | integration | 1.2.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | ongoing | 2020-12-02 19:58:10 |
| 5 | teamY | production | production | 1.0.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 6 | teamY | production | production | 1.1.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 7 | teamY | development | dev | 1.3.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | ongoing | 2020-12-02 19:58:10 |
| 8 | teamY | development | integration | 1.2.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 9 | teamZ | production | production | 1.0.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 10 | teamZ | production | production | 1.1.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | ongoing | 2020-12-02 19:58:10 |
| 11 | teamZ | development | dev | 1.3.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 12 | teamZ | development | integration | 1.2.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 13 | teamZ | development | test | 0.2.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:10 |
| 14 | teamZ | preproduction | preproduction | 1.1.0 | https://jsonplaceholder.typicode.com/ | {\"a\":\"b\"} | deployed | 2020-12-02 19:58:11 |
+-------------+----------+---------------+---------------+---------+---------------------------------------+---------------+----------+---------------------+
Sometimes, you may need to fetch dynamically latest deployment. You can fetch it like so:
curl '0:8080/api/v1/read/environment/latest?workload=teamX&environment=production&platform=production'
It will query latest version with status
equal to deployed
or completed
.
You can also use:
curl '0:8080/api/v1/read/environment/latest/whatever?workload=teamX&environment=production&platform=production'
It will fetch the latest version deployed without checking the status
of the deployment.
Golang metrics are built-in in our API.
We also add last 10 days deployments by status on curl 0:8080/api/v1/stats/latest
but also on curl 0:9101/metrics |grep versions_last_deployments_by_status
To enable logging on health(z) path, set environment variable to any value for example: APP_SKIP_PATH_DISABLED=true
.
The home page show you the last deployments from all workloads:
The statistic page show you how much deployments have by done:
The platform page show you deployments from selected plaform:
The environment page show you deployments from selected environment:
The raw page show you the content of the version deployed:
In order to contribute to our project, we need to configure git hooks.
You need first do install golangci-lint
Then, enable the hook in our project:
git config core.hooksPath .githooks
When you need to run both ui
and api
you need to open 2 shells:
# api shell
export SQL_DRIVER=postgres
export DB_URI="postgres://USERNAME:PASSWORD@HOST:PORT/DB_NAME?sslmode=disable"
export APP_PORT=8081
go run main.go
# ui shell
cd ui
export API_GATEWAY=http://127.0.0.1:8081
npm run dev
Once everything is working, you can test the result in docker:
sudo docker build -t versions:latest .
MY_LOCAL_IP=192.168.1.15 # for example
sudo docker run --rm -e SQL_DRIVER=postgres -e DB_URI="postgres://versions:versions@${MY_LOCAL_IP}:5432/versions?sslmode=disable" -p 8080:8080 docker.io/library/versions:latest