{"id":17166410,"url":"https://github.com/gdsoumya/better_ci","last_synced_at":"2025-04-13T15:06:20.523Z","repository":{"id":109963848,"uuid":"277336885","full_name":"gdsoumya/better_ci","owner":"gdsoumya","description":"Just a Better CI that you always wanted. Allows you to deploy PRs temporarily for a preview. Works with Docker-Compose and K8s deployments.","archived":false,"fork":false,"pushed_at":"2020-10-05T09:17:08.000Z","size":19826,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T15:06:15.577Z","etag":null,"topics":["ci","docker","golang","infrastructure","k8s","on-demand-service"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gdsoumya.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-07-05T16:06:00.000Z","updated_at":"2020-10-05T09:17:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"e866a77d-bab7-4152-9e03-e4349b659874","html_url":"https://github.com/gdsoumya/better_ci","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsoumya%2Fbetter_ci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsoumya%2Fbetter_ci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsoumya%2Fbetter_ci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsoumya%2Fbetter_ci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gdsoumya","download_url":"https://codeload.github.com/gdsoumya/better_ci/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248732485,"owners_count":21152852,"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":["ci","docker","golang","infrastructure","k8s","on-demand-service"],"created_at":"2024-10-14T23:05:29.919Z","updated_at":"2025-04-13T15:06:20.496Z","avatar_url":"https://github.com/gdsoumya.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Better CI\n\nJust a Better CI that you always wanted. Allows you to deploy PRs temporarily for a preview. Works with Docker-Compose and K8s deployments.\n\n## Prerequisites\n\n1. [Docker](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04) and [Docker-Compose](https://docs.docker.com/compose/install/)\n2. Kubectl configured [Tested on Kubeadm setup]\n\n## Start CI\n1. Cone Repo\n\n```sh\n$ git clone https://github.com/gdsoumya/better_ci.git\n$ cd better_ci\n```\n2. Create .env file with :\n* All Fields except `HOST` are compulsory\n* `ACCESS_KEY` only needs `public_repo` access if not used with private repos\n* If `HOST` is missing from`.env` the `public ip` of the system is used.\n* `AUTHOR_PERMISSION` can have values representing the author permission levels, it can be `OWNER`, `COLLABORATOR`, `CONTRIBUTOR`, `MEMBER` etc. or `ANY` for all permission levels. The value can be the combination of the different permissions, separated by space.\u003cbr\u003eEg. `AUTHOR_PERMISSION=OWNER COLLABORATOR`\n  \n```\nHOST=\u003coptional-field-for-public-ip-or-hostname\u003e\nPORT=\u003cport-to-run-ci-server\u003e\nGITHUB_USERNAME=\u003cyour-github-username\u003e\nACCESS_KEY=\u003cyour-personal-github-access-key\u003e\nDOCKER_USER=\u003cdocker-username-for-builds\u003e\nDOCKER_PASS=\u003cdocker-password\u003e\nWEBHOOK_SECRET=\u003cwebhook-secret\u003e\nAUTHOR_PERMISSION=\u003cauthor-association-allowed-to-deploy\u003e\n```\n3. Start CI Server\n\n    ```sh\n    $ go build -o ./output/ .\n    $ ./output/better_ci\n    ```\n    or\n\n    ```sh\n    $ go run . \n    ```\n\n## Setup Repo\n\n1. Add a Web Hook to your repo with the CI server URL. The WebHook only needs `Issue comments` event access. \n\n```\nWebHook URL : http://\u003cHOST\u003e:\u003cPORT\u003e/webhook\n```\n\n2. Add Better CI Config to deploy preview builds\n\n    Add a `.betterci/` dir at the root of your repo with a `config.json` file.\n    \n    Example `config.json`\n    \n* Docker-Compose Version : `.betterci/config.json`\n```json\n{\n    \"cmd\":[\"echo hello\",\"ls -al\"],\n    \"build\":[{\n        \"name\":\"nginx\",\n        \"file\":\"app/frontend/Dockerfile.client-local\",\n        \"context\":\"app/frontend\",\n        \"push\": false\n        },{\n        \"name\":\"server\",\n        \"file\":\"app/backend/build/Dockerfile.server\",\n        \"context\":\"app/backend\",\n        \"push\":true\n    }],\n    \"docker-compose\":\"app/better-ci-compose.yml\"\n}\n```   \n\n* K8s Version : `.betterci/config.json`\n```json\n{\n    \"cmd\":[\"echo hello\",\"ls -al\"],\n    \"build\":[{\n        \"name\":\"nginx\",\n        \"file\":\"app/frontend/Dockerfile.client-local\",\n        \"context\":\"app/frontend\",\n        \"push\": true\n        },{\n        \"name\":\"server\",\n        \"file\":\"app/backend/build/Dockerfile.server\",\n        \"context\":\"app/backend\",\n        \"push\":true\n    }],\n    \"k8s-manifest\":\"litmus-portal/k8s-manifest.yml\"\n}\n``` \n\n### Config File Doc\n1. **cmd** : A string array containing simple bash commands to execute, could be used to run tests etc. Currently compound commands like `cd dir \u0026\u0026 ls` are not allowed and also `cd` command isn't possible to execute(limitation of go:os/exec)\n2. **build** : An object array, containing details of the images to be built dynamically during preview deployment.\u003cbr\u003eThe Object contains the following fields:\n```\n{\n    \"name\" : \"\u003cname for the image\u003e\",\n    \"file\" : \"\u003crelative file path to Dockerfile template\u003e\",\n    \"context\" : \"\u003crelative path of context for build\u003e\",\n    \"push\" : \u003cbool to push to docker hub, used for k8s-manifests\u003e\n}\n```\nThe field `name` can be later reused in the Docker-Compose or K8s-Manifest Templates as variables to use the dynamically generated images for the deployment.\n\n**All relative paths are with respect to the root of the repository.**\n    \n3. **docker-compose** | **k8s-manifest** : A string denoting the relative path to the docker-compose file template or k8s-maifest template, both cannot be used at the same time. If used either error will be thrown or docker-compose will be given preference.\n\n### Docker-Compose Template\nThe Docker compose template allows 2 variables :\n1. **#{image-name}** : `image-name` is the name of the image you mentioned in the `build` stage, which is dynamically generated during build. It can be used to build the current image of the PR and use it, without pushing or storing it permanently.\n2. **#{PORT}** : `PORT` can be used to dynamically select the port to expose a container service, it is adviced to use this when you have to expose port on the system to access the container services. The `PORT` value will be added to the comment in the PR after preview deployment, for access.\n\n* **Remember not to give any container-name, it will be auto generated**\n\nExample Docker-Compose Template :\n```\nversion: '3'\n\nservices:\n    nginx-server:\n        ports:\n            - #{PORT}:80\n\timage: #{nginx}\n    backend-server:\n\timage: #{server}\n```  \n### K8s Template\nThe K8s deployments only works with `nodePort` Services and allows the following variables:\n1. **#{image-name}** : `image-name` is the name of the image you mentioned in the `build` stage, which is dynamically generated during build. It can be used to build the current image of the PR and use it, without pushing or storing it permanently.\n\n* **Remember to use `\"push\":true` in the `build` stage for the images used in the k8s deployment**\n* **The namespaces for the deployments are auto-generated hence,specifying namespace can cause errors**\n* **Do not mention the `nodePort` value in the template, as it may cause conflicts with other deployments**\n\nExample K8s Template :\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: backend-server\n  labels:\n    component: backend-server\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      component: backend-server\n  template:\n    metadata:\n      labels:\n        component: backend-server\n    spec:\n      containers:\n      - name: backend-server\n        image: #{server}\n        ports:\n        - containerPort: 8080\n        imagePullPolicy: Always\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: backend-server-service\nspec:\n  type: NodePort\n  ports:\n    - name: http\n      port: 9002\n      targetPort: 8080\n  selector:\n    component: backend-server\n```\n\n**The templates can be separately defined from the actual deployment files, so you can have a `docker-compose.yml` and a `ci-docker-compose.yml` at the same time. Just make sure to mention the correct file path in the -`.betterci/config.json`**\n\n## Initiate Preview\n\nTo start the preview build of a PR in a registered repo -\n* Comment In the PR: **/preview**\n* Comment In the PR: **/preview `\u003cinteger\u003e`**\n\nThe first form will deploy the preview for a default time of `5mins` the second will deploy it for `\u003cinteger\u003emins`\n\nThe links of the exposed services in both docker-compose and k8s case will be added to the comment automatically once they are deployed. Once the link expires an expired message gets edited into the comment itself.\nCurrently, only one build can be active per PR, so once a build is initiated you have to wait before it expires to perform a new build of the PR. \n\n## Author\n* Soumya Ghosh Dastidar\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgdsoumya%2Fbetter_ci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgdsoumya%2Fbetter_ci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgdsoumya%2Fbetter_ci/lists"}