{"id":16112503,"url":"https://github.com/abdulsametileri/web-based-todo-list-application","last_synced_at":"2025-03-18T09:31:07.497Z","repository":{"id":81890244,"uuid":"364916825","full_name":"Abdulsametileri/web-based-todo-list-application","owner":"Abdulsametileri","description":"Golang + vue.js + nginx + docker-compose + github action","archived":false,"fork":false,"pushed_at":"2021-12-20T20:33:55.000Z","size":973,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-16T18:43:18.224Z","etag":null,"topics":["docker-compose","github-actions","golang","tdd-golang","tdd-javascript","vuejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Abdulsametileri.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2021-05-06T13:17:33.000Z","updated_at":"2024-04-17T04:52:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"d6c510f3-e6a5-42e3-88be-cf9395693609","html_url":"https://github.com/Abdulsametileri/web-based-todo-list-application","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abdulsametileri%2Fweb-based-todo-list-application","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abdulsametileri%2Fweb-based-todo-list-application/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abdulsametileri%2Fweb-based-todo-list-application/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abdulsametileri%2Fweb-based-todo-list-application/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Abdulsametileri","download_url":"https://codeload.github.com/Abdulsametileri/web-based-todo-list-application/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244192568,"owners_count":20413550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["docker-compose","github-actions","golang","tdd-golang","tdd-javascript","vuejs"],"created_at":"2024-10-09T20:08:12.630Z","updated_at":"2025-03-18T09:31:07.121Z","avatar_url":"https://github.com/Abdulsametileri.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Web Based ToDo List Application\n\n## To Do List\n\n- [x] 1- User interface for ONLY adding ToDo’s\n- [x] 2- Back-end service to store a persistent state of ToDo list\n- [x] 3- Writing deployment files of your front-end and back-end\n- [x] 4- Automating build, test and deployment of your application via CI/CD pipeline\n- [x] 5- Dockerize both your front-end and back-end application to make them ready for deployment.\n- [x] 6- Deploy your application to a Kubernetes cluster or Docker Swarm or into a VM using a cloud provider\n- [x] 7- Write deployment configurations(i.e. Kubernetes config files, Docker Swarm files etc.) for each project.\n\n## Tech Stack\n\n\u003col\u003e\n\u003cli\u003eGoLang (backend)\n    \u003col\u003e\n        \u003cli\u003egin (web framework)\u003c/li\u003e\n        \u003cli\u003etestify (test framework)\u003c/li\u003e\n        \u003cli\u003emap for in-memory database\u003c/li\u003e\n        \u003cli\u003ebuild tags for go compiler [dev, prod, testenv]\u003c/li\u003e\n    \u003c/ol\u003e\n\u003c/li\u003e\n\n\u003cli\u003e Vue (frontend) \n    \u003col\u003e\n        \u003cli\u003eaxios (API calls)\u003c/li\u003e\n        \u003cli\u003eunit tests (vue-test-utils)\u003c/li\u003e\n        \u003cli\u003ee2e tests (Cypress) `Dockerfile-e2e`\u003c/li\u003e\n        \u003cli\u003econsumer driven contract test (apiblueprint \u0026\u0026 dredd) `Dockerfile-contractTests` \u003c/li\u003e\n    \u003c/ol\u003e\n\u003c/li\u003e\n\n\u003cli\u003eNginx (Web server)\n    \u003col\u003e\n        \u003cli\u003enginx-prod.conf =\u003e Production\u003c/li\u003e\n        \u003cli\u003enginx-test.conf =\u003e Development\u003c/li\u003e\n    \u003c/ol\u003e\n\u003c/li\u003e\n\n\n\u003cli\u003eGithub Actions (CI)\n    \u003col\u003e\n        \u003cli\u003edeploy2TestEnv.yml for test enviroment (Brach: [test]) \u003c/li\u003e\n        \u003cli\u003edeploy2ProdEnv.yml for production enviroment (Branch: [master]) \u003c/li\u003e\n    \u003c/ol\u003e\n    All workflows runs on 'self-hosted' means our AWS machines. \u003cbr/\u003e \n    Test env: aws-ec2-test \u003cbr/\u003e \n    Prod evv: aws-ec2 \u003cbr/\u003e\n    (Reason of the choosing Github Actions for CI/CD, my experience)\n\u003c/li\u003e\n\n\u003cli\u003eDocker \u0026\u0026 Docker-Compose\u003c/li\u003e\n\n\u003cli\u003e2 Free Tier instance on Amazon EC2 (1 Test Env, 1 Production Env)\u003c/li\u003e\n\u003c/ol\u003e\n\n## Directory Structure\n```\n.\n├── Dockerfile // Dockerfile backend\n├── config // Config for backend\n├── controllers // Backend APIs and their tests\n├── docker-compose-prod.yml \n├── docker-compose-test.yml\n├── frontend\n│   ├── Dockerfile // Dockerfile frontend\n│   ├── Dockerfile-contractTests // Dockerfile apiblueprint dredd\n│   ├── Dockerfile-e2e // Dockerfile cypress\n│   ├── api-description.apib \n│   ├── cypress.json\n│   ├── dredd.yml // Dredd settings\n│   ├── nginx-prod.conf \n│   ├── nginx-test.conf\n│   ├── src\n│   ├────── App.vue // App Todo UI\n│   ├────── api.js // Axios API Calls\n│   └── main.js\n│   ├── tests\n│   ├────── e2e\n│   └────── unit\n├── go.mod\n├── go.sum\n├── main.go\n\n```\n\n## Architecture Decision\n\n0. Two braches test and master (prod) enviroment.\n\n1. I could use `embed` directive in Golang to serve static app files (Vue).\nBut I wanted to learn nginx+vue+go stack and implement. Because of this I did not use\n`embed`.\n\n2. I used two different servers for test and prod in aws cloud provider. \nI wanted to run ui acceptance test and api consumer driven contract test \nin live enviroment in different server. \n(Reason of the choosing AWS, just experience)\n\n3. I created two nginx-{test,prod} file because of the differentation of server name in nginx conf.\nWith this distinction I could handle cors etc. easily\n\n```\n listen       80;\n server_name  ec2-52-59-226-235.eu-central-1.compute.amazonaws.com;\n\n location /api/v1 {\n   if ($request_method = 'OPTIONS') {\n      add_header Access-Control-Allow-Origin '*' always;\n      ...\n      ....\n```\n\n4. I created three dockerfile Dockerfile{,contractTests,e2e} for frontend. Because of this\nI can easily builds according to the enviroment.\n\n5. I used **multi-stage build** for my dockerfiles to reduce \nproduced image size.\n\n6. I used testenv for backend, and test for frontend as build args. So,\nI could easily build docker images for different enviroment just a one Dockerfile.\n\n```\nbackend:\n   build:\n     context: \".\"\n     args:\n       - ENV=testenv\n\nnginx-frontend:\n    build:\n      context: ./frontend/\n      args:\n        - ENV=test\n```\n\nBackend Dockerfile, I gave $ENV variable from docker-compose for build \ndifferent enviroments.\n\n```\n..\nRUN go mod download\nCOPY . .\n\nRUN CGO_ENABLED=0 go test --tags $ENV ./...\nRUN CGO_ENABLED=0 GOOS=linux go build --tags $ENV -o main main.go\n..\n```\n\nFrontend Dockerfile, I gave $ENV to run related vue build \nand load (nginx-test or nginx-prod) nginx file.\n \n```\n..\nCOPY . .\nRUN npm run test:unit \u0026\u0026 npm run build-for-$ENV\n\nFROM nginx:stable-alpine as production-stage\nARG ENV\nRUN mkdir /app\nCOPY --from=build-stage /app/dist /app\nCOPY --from=build-stage /app/nginx-$ENV.conf /etc/nginx/nginx.conf\n..\n```\n\n## Pipeline automation\n\n![](images/pipelinearch.png)\n\n![](images/action-runners.png)\n\n![](images/ec2-instances.png)\n\nTerminated.\n\n## Development enviroment\n\n### With standole\n\nFor our backend app, you must give \"tag\" for go compiler. \n\n`$ go run --tags dev main.go` \n\nit runs **:3000**\n\nFor tests: \n\n`$ go test --tags dev ./...`\n\n#### APIs\n\n`[POST]` `api/v1/addTodo` \n\n`$ curl -H \"Content-type: application/json\" localhost:3000/api/v1/getTodoList`\n\n`[GET]` `api/v1/getTodolist` \n\n`$ curl -H \"Content-type: application/json\" -X POST -d '{\"task_description\":\"dummy\"}' localhost:3000/api/v1/addTodo`\n\n`[GET]` `api/v1/deleteAllTodos`\n\n`$ curl -H \"Content-type: application/json\" localhost:3000/api/v1/deleteAllTodos`\n\nFor the frontend development server you can run \n\n`$ npm run serve` \n\nit runs **:8080**\n\nFor Unit tests:\n\n`npm run test:unit`\n\n### With Docker compose\n\n`$ docker-compose -f docker-compose-{test,prod}.yml up --build -d`  ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabdulsametileri%2Fweb-based-todo-list-application","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabdulsametileri%2Fweb-based-todo-list-application","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabdulsametileri%2Fweb-based-todo-list-application/lists"}