{"id":45730092,"url":"https://github.com/mekomsolutions/openmrs-cd","last_synced_at":"2026-02-25T09:21:18.424Z","repository":{"id":26305078,"uuid":"106390769","full_name":"mekomsolutions/openmrs-cd","owner":"mekomsolutions","description":"A Continuous Delivery platform for OpenMRS and Bahmni servers","archived":false,"fork":false,"pushed_at":"2024-11-04T08:17:58.000Z","size":1867,"stargazers_count":5,"open_issues_count":1,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-04T09:24:57.613Z","etag":null,"topics":["bahmni","continuous-delivery","docker","jenkins","openmrs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/mekomsolutions.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":"2017-10-10T08:38:03.000Z","updated_at":"2024-11-04T08:18:02.000Z","dependencies_parsed_at":"2023-11-16T13:41:01.343Z","dependency_job_id":"9906b36f-1fb8-4ec2-8495-4dea51feebe9","html_url":"https://github.com/mekomsolutions/openmrs-cd","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mekomsolutions/openmrs-cd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mekomsolutions%2Fopenmrs-cd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mekomsolutions%2Fopenmrs-cd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mekomsolutions%2Fopenmrs-cd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mekomsolutions%2Fopenmrs-cd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mekomsolutions","download_url":"https://codeload.github.com/mekomsolutions/openmrs-cd/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mekomsolutions%2Fopenmrs-cd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29815727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T05:36:42.804Z","status":"ssl_error","status_checked_at":"2026-02-25T05:36:31.934Z","response_time":61,"last_error":"SSL_read: 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":["bahmni","continuous-delivery","docker","jenkins","openmrs"],"created_at":"2026-02-25T09:21:17.663Z","updated_at":"2026-02-25T09:21:18.408Z","avatar_url":"https://github.com/mekomsolutions.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![alt tag](readme/ocd3.png)\n\n# OpenMRS CD 3 (OCD3)\n\u003e A dockerized [Jenkins](https://jenkins.io/) server ready to manage dockerized [OpenMRS](https://openmrs.org/) and [Bahmni](https://www.bahmni.org/) instances.\n\nOCD3 in a nutshell:\n* Builds and deploys all OpenMRS or Bahmni related software artifacts.\n* Provides a definition framework for OpenMRS and Bahmni servers.\n* Delivers server instances to Linux-powered hosts.\n* Tracks code and configuration changes and propagates them to its managed server instances.\n\n## User guide\n\n*How to build and deploy a project?*\n\nThere are multiple options depending of the type of project you are deploying, but mainly the 3 following ones should cover 99% of cases:\n- default\n- maven\n- distribution\n\nThe build is triggered by a Webhook that must be added to your hosting SCM service (GitHub, GitLab...).\nThe Webhook expects 2 query parameters:\n\n* `[projectType=default|maven|distribution ...]`. Defaults to default. See list of all supported project types here\n\n* `[credentialsId=\u003carbitrary_name_of_the_credentials_entry_in_Jenkins_to_clone_the_repo\u003e]` . Defaults to gitHubCredentials.\nEg:\nhttps://username:password@localhost:8080/generic-webhook-trigger/invoke?projectType=default\u0026credentialsId=myGitLabRepoCredentials\n\n\u003cdetails\u003e\n\n\u003csummary\u003eHow to configure Webhook for OCD3 on GitHub?\u003c/summary\u003e\n\n### Add Webhook\n\n\u003cimg src=\"readme/gh_add_webhook.png\" width=\"700\"\u003e\n\n### Create Webhook\n\n\u003cimg src=\"readme/gh_create_webhook.png\" width=\"700\"\u003e\n\n### Verify Webhook\n\n\u003cimg src=\"readme/gh_verify_webhook.png\" width=\"700\"\u003e\n\nSee [here](https://docs.github.com/en/developers/webhooks-and-events/webhooks/about-webhooks) for additional documentation.\n\n\u003c/details\u003e\n\n\n#### `default`:\n\nThe `default` project type should cover most cases. It assumes that build and deploy instructions are provided in a custom file present at the root of the project and named **.ocd3.yml** (or .ocd3.yaml)\n\nThe **.ocd3.yml** file should display as below:\n```\nversion: 1\nbuild:\n  bash_commands: \u003cbash command\u003e\ndeploy:\n  bash_commands: \u003cbash command\u003e\n  artifact:\n    groupId: \u003ca group ID\u003e\n    artifactId: \u003ca artifact ID\u003e\n    version: \u003ca version\u003e\nrebuildOnDependencyChanges: true|false\n```\nNote that the `artifact` section is **required only if your project is not a Maven project**.\nNote that the `rebuildOnDependencyChanges`, if set to `true`, will parse the project's POM file and save its dependencies so to later rebuild when any dependending artifact has changed.\n\nSee an example for a Maven project:\n```\nversion: 1\nbuild:\n  bash_commands: \"mvn clean test\"\ndeploy:\n  bash_commands: \"mvn clean deploy -DskipTests -DaltDeploymentRepository=mks-nexus::default::https://nexus.mekomsolutions.net/repository/maven-snapshots\"\nrebuildOnDependencyChanges: \"true\"\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow webhook URL:\u003c/summary\u003e\n\n```\nhttps://\u003cuser\u003e:\u003cpassword\u003e@openmrs-cd.mekomsolutions.net/generic-webhook-trigger/invoke\n```\n\u003c/details\u003e\n\n\n#### `maven`:\n\nThis project type will suit to most Maven projects that simply need to apply standard Maven commands:\n- `mvn clean install`\n- `mvn clean deploy -DaltDeploymentRepository=...`\n- with some additional nuances\n\n\u003cdetails\u003e\n\u003csummary\u003eShow webhook URL:\u003c/summary\u003e\n\n```\nhttps://\u003cuser\u003e:\u003cpassword\u003e@openmrs-cd.mekomsolutions.net/generic-webhook-trigger/invoke?projectType=maven\n```\n\u003c/details\u003e\n\n\n#### `distribution`:\n\nA special project type to not only build the project using standard Maven commands but also save its Maven dependencies in a way that the distribution is rebuilt anytime one of the dependency has been rebuilt.\n\n\u003cdetails\u003e\n\u003csummary\u003eShow webhook URL:\u003c/summary\u003e\n\n```\nhttps://\u003cuser\u003e:\u003cpassword\u003e@openmrs-cd.mekomsolutions.net/generic-webhook-trigger/invoke?projectType=distribution\n```\n\u003c/details\u003e\n\n#### `openmrsmodule`, `initializer`, `odooaddon`...:\n\nThere are other types available but most of them are now deprecated, being replaced by the 3 ones described above.\n\nThe full list can be found in the [src/pipeline1/impl/](node-scripts/src/pipeline1/impl) folder.\n\n*How to deploy a server?*\n\n**(WIP)**\n\n\n#### Using secrets in the Instance Event:\n\nTo avoid entering clear text secrets in an instance event, one can configure Jenkins Credentials functionality and use the special syntax `jenkinsCredentials(\u003cpath\u003e)` anywhere in the instance. See more on Jenkins Credentials [here](https://www.jenkins.io/doc/book/using/using-credentials/).\nFor example:\n\n```\n{\n  group: hsc\n  type: dev\n  envVars:{\n    \"OPENMRS_USERNAME\": \"jenkinsCredentials(openmrs.password)\",\n    \"PROXY_PORT\": \"80\",\n    ...\n  }\n}\n```\n\nThis will allow to substitute the placeholder with the matching Jenkins Credentials secret value.\n\nHowever, Jenkins needs to be configured in a specific way for the secrets to be picked up.\n\n- Credentials must be of type \"Secret text\".\n- The name of the Credentials must either be a `group` or a pair `group_type`\n- The \"Secret\" (text) should be a JSON object.\nThe secret object will then be accessible in the instance event and can be navigated through using **dot notation.**\nAny amount of depth is allowed.\n\nIn the example above, the secret would look like:\n\n```\n{\n  \"openmrs\": {\n    \"password\": \"password123\",\n    ...\n  },\n  ...\n}\n\n```\n\nTo be made available in an instance definition, the Jenkins Credential should either be named after the instance group (eg, `hsc`) or the pair group_type (eg, `hsc_dev`).\nAll instances matching the group or group/type pair will be able to use the secret.\n\nIf providing conflicting secret keys, a merge strategy is applied and the group/type credentials will take precedence over the group.\n\n\n## Developer Guide\n\n\u003eOCD3 is a Dockerized Jenkins with preconfigured jobs. Those jobs run Node JS scripts or Node-generated Bash scripts.\n\nThis explains the structure and content of the root folder of the project:\n\n```\n.\n├── docker\n├── jenkins\n└── node-scripts\n```\n**node-scripts** is the Node JS scripts area, **docker** holds the Dockerfile (and other resources needed to configure the container) and **jenkins** contains the parts of Jenkins home that are preconfigured, as well as the pipelines' Jenkinsfiles.\n\nGradle is used to run all build tasks and package all artifacts that make OCD3.\n\n### Working out of the sources directly\n\nWhen developing on the CD the best is to mount the Docker volumes right out of the sources.\n\n**1** - Clone the openmrs-cd repository:\n\n**Note:** _we assume that cloned repositories should go into the home `~/repos` folder. Adapt the commands below in accordance to your own local setup._\n```bash\nmkdir -p ~/repos \u0026\u0026 cd ~/repos \u0026\u0026 \\\n  git clone https://github.com/mekomsolutions/openmrs-cd \u0026\u0026 cd openmrs-cd\n```\n**2** - Build the Node scripts:\n```bash\n./gradlew node-scripts:build\n```\n\n**3** - Run the `openmrscd` container:\n```bash\ndocker-compose up\n```\n\n### The 'node-scripts' component\nDeveloping on OCD3 means working in here most of the time.\nThat is because the bulk of the logic of what OCD3 does lives here. Almost all Jenkins jobs are built on the following pattern:\n\u003eJenkins jobs run Node scripts that generate Bash scripts that in turn perform the core CD tasks.\n\nThis is how one would build the underlying Node JS scripts:\n```bash\n./gradlew node-scripts:build\n```\nAnd this must be done before submitting code commits.\nHowever note that the code base is not really built into anything since the container links directly to **/node-scripts**, but this formats the code and runs the test suite.\n\nA detailed developer guide about the Node scripts can be found [here](readme/node-scripts/README.md).\n\n### The 'docker' component\nSee [here](readme/docker/README.md).\n\n### The 'jenkins' component\n\nOCD3 not only needs a Docker image for its binaries but also requires a 'Jenkins home' folder that provides a pre-configured Jenkins setup:\n\n```bash\n./gradlew jenkins:build\n```\nThis will package a zip archive of the jenkins folder.\n\n**Note:** _Developing with the jenkins component may require to use `git clean -Xdf` from time to time. Please read the [note for developpers](readme/jenkins/README.md) first._\n\n### The parent project (root folder)\n\nFinally it is possible to build everything at once from the root level:\n```bash\n./gradlew build\n```\nThis will cascade down to all child builds and run them.\n\nTo then deploy:\n\n```\nexport mksRepoUrl=...\nexport mksRepoUsername=...\nexport mksRepoPassword=...\n```\n\n```\n./gradlew deploy\n```\n\n## Starting OCD3 for production\n\nThe following steps describe a way to gather OCD3 artifacts locally and run the Docker container based on them. In a Un\\*x shell:\n\n**1** - Set the target version:\n```bash\nexport VERSION=3.0.0-SNAPSHOT\n```\n**2** - Copy the artifacts out of the Nexus repo into the local Maven repo:\n```bash\nmvn dependency:get \\\n  -DgroupId=net.mekomsolutions \\\n  -DartifactId=openmrs-cd \\\n  -Dversion=$VERSION \\\n  -Dpackaging=zip \\\n  -DremoteRepositories=https://nexus.mekomsolutions.net/repository/maven-public\n```\n**3** - Unpack everything into openmrs-cd on the home folder:\n```bash\nmvn dependency:copy -Dartifact=net.mekomsolutions:openmrs-cd:$VERSION:zip -DoutputDirectory=/tmp/ \u0026\u0026 unzip /tmp/openmrs-cd-$VERSION.zip -d /tmp/ \u0026\u0026 rm /tmp/openmrs-cd-$VERSION.zip \u0026\u0026 rsync -av --delete /tmp/openmrs-cd-$VERSION/ ~/openmrs-cd/ \u0026\u0026 rm -r /tmp/openmrs-cd-$VERSION\n```\n\n**4** - Run the `openmrscd` container:\n```bash\ndocker run -dti --name openmrscd  -p 8080:8080 \\\n  -v ~/openmrs-cd/node-scripts:/opt/node-scripts \\\n  -v ~/openmrs-cd/jenkins_home:/var/jenkins_home \\\n  -v ~/openmrs-cd/app_data:/var/lib/openmrs_cd/app_data \\\n  mekomsolutions/openmrscd:$VERSION\n```\nAfter the container has started, the customized Jenkins instance will be accessible at [http://localhost:8080](http://localhost:8080) with the following credentials: **admin** / **password**.\n\nAuthorize 'jenkins' user to write to the app_data folder:\n```bash\ndocker exec -it openmrscd \\\n  bash -c \"sudo chown -R jenkins:jenkins /var/lib/openmrs_cd/app_data/\"\n```\n\n**Attention:** _The app data folder will contain the CD's file-based database. Make sure to keep it in a safe location._\n\n**5** - Setup your Maven repo:\nYou must configure the coordinates of your Maven repo if you intend to deploy your own Maven artifacts with the CD.\nLaunch the **artifact_repo.js** script to configure the artifacts repository credentials and artifacts upload URLs:\n```bash\ndocker exec -it openmrscd \\\n  bash -c \"cd /usr/share/jenkins/ \u0026\u0026 npm install \u0026\u0026 node artifact_repo.js\"\n```\nAnd answer the prompted questions.\n\n**Note:** _If you do not want to enter the artifacts repository URLs and authentication details by hand (through the CLI) you can just edit **usr/share/jenkins/artifact_repo_default.json** (see the default one [here](docker/config/artifact_repo_default.json) as an example) with your own repo URLs and ID and then run the script again. It will detect the file and ask you to use it._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmekomsolutions%2Fopenmrs-cd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmekomsolutions%2Fopenmrs-cd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmekomsolutions%2Fopenmrs-cd/lists"}