{"id":37134847,"url":"https://github.com/lord-y/versions","last_synced_at":"2026-01-14T15:43:55.404Z","repository":{"id":65194343,"uuid":"317584363","full_name":"Lord-Y/versions","owner":"Lord-Y","description":"Versions provide a source of truth of your application deployment history","archived":false,"fork":false,"pushed_at":"2023-12-05T20:58:04.000Z","size":13458,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"dev","last_synced_at":"2024-06-20T12:05:42.717Z","etag":null,"topics":["application","deployment","version"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Lord-Y.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-01T15:27:54.000Z","updated_at":"2022-11-03T22:15:49.000Z","dependencies_parsed_at":"2023-12-05T15:28:50.685Z","dependency_job_id":"bb3d8617-5782-49e2-bbbf-7e1ccb11f5f0","html_url":"https://github.com/Lord-Y/versions","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/Lord-Y/versions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Y%2Fversions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Y%2Fversions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Y%2Fversions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Y%2Fversions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Lord-Y","download_url":"https://codeload.github.com/Lord-Y/versions/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Y%2Fversions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28424522,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T15:24:48.085Z","status":"ssl_error","status_checked_at":"2026-01-14T15:23:41.940Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["application","deployment","version"],"created_at":"2026-01-14T15:43:54.496Z","updated_at":"2026-01-14T15:43:55.379Z","avatar_url":"https://github.com/Lord-Y.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# versions [![CircleCI](https://circleci.com/gh/Lord-Y/versions/tree/main.svg?style=svg)](https://circleci.com/gh/Lord-Y/versions?branch=main)\n\n`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.\n\n## Definitions\n\n`Workload`: it mean which team is related to this deployment.\n\n`Platform`: release to which platform your application has been deployed like development, staging, preproduction or production.\n\n`Environment`: on each platform, multiple environment can be deployed like development or integration.\n\n## How it works\n\nYou need to define OS environment variables like so:\n\n```bash\n# for mysql\nexport SQL_DRIVER=mysql\nexport DB_URI=\"USERNAME:PASSWORD@tcp(HOST:PORT)/DB_NAME?charset=utf8\u0026autocommit=true\u0026multiStatements=true\u0026maxAllowedPacket=0\u0026interpolateParams=true\u0026parseTime=true\"\n# for postgres\nexport SQL_DRIVER=postgres\nexport DB_URI=\"postgres://USERNAME:PASSWORD@HOST:PORT/DB_NAME?sslmode=disable\"\n# If you want to enable a redis\nexport REDIS_ENABLED=true\nexport REDIS_URI=redis://:xxxxx@host:port/db\n# or \nexport REDIS_ENABLED=true\nexport REDIS_URI=redis://:xxxxx@host:port\n```\n\nSQL_DRIVER can only be `mysql` or `postgres`\nAt startup, the DB initialization or migration will be handle.\n\nHere are the supported versions:\n- postgres 10 and above\n- mariadb 10.x and above\n- mysql 5.7 and above\n\n## Running port number\n\nPort number can be change:\n\n```bash\nexport APP_PORT=8080\n```\n\n## Tests\n\nUnit testing are covered.\n\n```bash\ngo test -v ./... -coverprofile=coverage.out\n# go tool cover -html=coverage.out\n# go tool cover -func=coverage.out\n```\n\n## Queries\n\nFor POST request, both content-type \n\n```bash\n# post requests with json\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\n\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\n\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\ncurl -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\"}'\n\n# post requests with form format mode\ncurl -XPOST 0:8080/api/v1/create -d 'version=1.1.0\u0026workload=teamX\u0026environment=production\u0026platform=production\u0026changelogURL=https://jsonplaceholder.typicode.com/\u0026raw=rawContent\u0026status=ongoing'\ncurl -XPOST 0:8080/api/v1/create -d 'version=1.3.0\u0026workload=teamX\u0026environment=production\u0026platform=production\u0026changelogURL=https://jsonplaceholder.typicode.com/\u0026raw=rawContent\u0026status=deployed'\ncurl -XPOST 0:8080/api/v1/create -d 'version=1.2.0\u0026workload=teamX\u0026environment=production\u0026platform=production\u0026changelogURL=https://jsonplaceholder.typicode.com/\u0026raw=rawContent\u0026status=failed'\n```\n\nEach `POST` return the id of the deployment like so `{\"versionId\":14}`.\nTo update the status of the deployment:\n```bash\ncurl -XPOST 0:8080/api/v1/update/status -H 'Content-type: application/json' -d '{\"versionId\": \"14\",\"status\": \"deployed\"}'\n```\n\nHere is an example of DB content:\n```bash\n+-------------+----------+---------------+---------------+---------+---------------------------------------+---------------+----------+---------------------+\n| versions_id | workload | platform      | environment   | version | changelog_url                         | raw           | status   | date                |\n+-------------+----------+---------------+---------------+---------+---------------------------------------+---------------+----------+---------------------+\n|           1 | teamX    | production    | production    | 1.0.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | ongoing  | 2020-12-02 19:58:10 |\n|           2 | teamX    | production    | production    | 1.1.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|           3 | teamX    | development   | dev           | 1.3.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | failed   | 2020-12-02 19:58:10 |\n|           4 | teamX    | development   | integration   | 1.2.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | ongoing  | 2020-12-02 19:58:10 |\n|           5 | teamY    | production    | production    | 1.0.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|           6 | teamY    | production    | production    | 1.1.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|           7 | teamY    | development   | dev           | 1.3.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | ongoing  | 2020-12-02 19:58:10 |\n|           8 | teamY    | development   | integration   | 1.2.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|           9 | teamZ    | production    | production    | 1.0.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|          10 | teamZ    | production    | production    | 1.1.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | ongoing  | 2020-12-02 19:58:10 |\n|          11 | teamZ    | development   | dev           | 1.3.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|          12 | teamZ    | development   | integration   | 1.2.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|          13 | teamZ    | development   | test          | 0.2.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:10 |\n|          14 | teamZ    | preproduction | preproduction | 1.1.0   | https://jsonplaceholder.typicode.com/ | {\\\"a\\\":\\\"b\\\"} | deployed | 2020-12-02 19:58:11 |\n+-------------+----------+---------------+---------------+---------+---------------------------------------+---------------+----------+---------------------+\n```\n\n## Get latest deployment\n\nSometimes, you may need to fetch dynamically latest deployment.\nYou can fetch it like so:\n```bash\ncurl '0:8080/api/v1/read/environment/latest?workload=teamX\u0026environment=production\u0026platform=production'\n```\nIt will query latest version with `status` equal to `deployed` or `completed`.\n\nYou can also use:\n```bash\ncurl '0:8080/api/v1/read/environment/latest/whatever?workload=teamX\u0026environment=production\u0026platform=production'\n```\nIt will fetch the latest version deployed without checking the `status` of the deployment.\n\n## Metrics\n\nGolang metrics are built-in in our API.\n\nWe 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`\n\n## Enable logging on health(z) paths\n\nTo enable logging on health(z) path, set environment variable to any value for example: `APP_SKIP_PATH_DISABLED=true`.\n\n## What does it looks like\n\nThe home page show you the last deployments from all workloads:\n\n![Home](./screenshots/home.png \"Home\")\n\nThe statistic page show you how much deployments have by done:\n\n![Staticstics](./screenshots/staticstics.png \"Staticstics\")\n\nThe platform page show you deployments from selected plaform:\n\n![Workloads platforms](./screenshots/workloads_platforms.png \"Workloads platforms\")\n\nThe environment page show you deployments from selected environment:\n\n![Workloads environments](./screenshots/workloads_environments.png \"Workloads environments\")\n\nThe raw page show you the content of the version deployed:\n\n![Raw version](./screenshots/raw_version.png \"Raw version\")\n\n## Contributing\n\nIn order to contribute to our project, we need to configure git hooks.\n\nYou need first do install [golangci-lint](https://golangci-lint.run/usage/install/)\n\nThen, enable the hook in our project:\n```bash\ngit config core.hooksPath .githooks\n```\nWhen you need to run both `ui` and `api` you need to open 2 shells:\n```bash\n# api shell\nexport SQL_DRIVER=postgres\nexport DB_URI=\"postgres://USERNAME:PASSWORD@HOST:PORT/DB_NAME?sslmode=disable\"\nexport APP_PORT=8081\ngo run main.go\n\n# ui shell\ncd ui\nexport API_GATEWAY=http://127.0.0.1:8081\nnpm run dev\n```\n\n## Docker\n\nOnce everything is working, you can test the result in docker:\n```bash\nsudo docker build -t versions:latest .\n\nMY_LOCAL_IP=192.168.1.15 # for example\nsudo 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\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flord-y%2Fversions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flord-y%2Fversions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flord-y%2Fversions/lists"}