{"id":19884191,"url":"https://github.com/opus-codium/puppet-application","last_synced_at":"2025-05-02T15:30:44.954Z","repository":{"id":37295253,"uuid":"458021663","full_name":"opus-codium/puppet-application","owner":"opus-codium","description":"Tooling for Continuous Delivery (CD) of applications in a Puppet managed environment by leveraging orchestration through Bolt or Choria.","archived":false,"fork":false,"pushed_at":"2024-11-13T20:56:27.000Z","size":190,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-23T22:39:40.195Z","etag":null,"topics":["bolt","cd","choria","ci","hacktoberfest","puppet"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/opus-codium.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-11T02:41:22.000Z","updated_at":"2024-11-13T20:56:25.000Z","dependencies_parsed_at":"2024-01-09T20:30:50.127Z","dependency_job_id":"466fcbd5-d9b7-4041-a060-f3583e43bbdb","html_url":"https://github.com/opus-codium/puppet-application","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opus-codium%2Fpuppet-application","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opus-codium%2Fpuppet-application/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opus-codium%2Fpuppet-application/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opus-codium%2Fpuppet-application/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opus-codium","download_url":"https://codeload.github.com/opus-codium/puppet-application/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252062705,"owners_count":21688583,"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":["bolt","cd","choria","ci","hacktoberfest","puppet"],"created_at":"2024-11-12T17:25:43.236Z","updated_at":"2025-05-02T15:30:44.947Z","avatar_url":"https://github.com/opus-codium.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# application\n\n\u003c!-- header GFM --\u003e\n[![Build Status](https://img.shields.io/github/actions/workflow/status/opus-codium/puppet-application/release.yml)](https://github.com/opus-codium/puppet-application/releases)\n[![Puppet Forge](https://img.shields.io/puppetforge/v/opuscodium/application.svg)](https://forge.puppetlabs.com/opuscodium/application)\n[![Puppet Forge - downloads](https://img.shields.io/puppetforge/dt/opuscodium/application.svg)](https://forge.puppetlabs.com/opuscodium/application)\n[![Puppet Forge - endorsement](https://img.shields.io/puppetforge/e/opuscodium/application.svg)](https://forge.puppetlabs.com/opuscodium/application)\n[![Puppet Forge - scores](https://img.shields.io/puppetforge/f/opuscodium/application.svg)](https://forge.puppetlabs.com/opuscodium/application)\n[![License](https://img.shields.io/github/license/opus-codium/puppet-application.svg)](https://github.com/voxpupuli/opuscodium-application/blob/master/LICENSE.md)\n\u003c!-- header --\u003e\n\n#### Table of Contents\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n* [Module description](#module-description)\n* [Usage](#usage)\n\t* [Declaring an application](#declaring-an-application)\n\t* [mtree integration](#mtree-integration)\n\t* [Hooks](#hooks)\n\t* [Continuous Deployment (CD)](#continuous-deployment-cd)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n## Module description\n\nThis Puppet module provide tooling for Continuous Delivery (CD) of applications in a Puppet managed environment by leveraging orchestration through [Bolt](https://puppet.com/docs/bolt/latest/bolt.html) or [Choria](https://choria.io/).\n\n## Usage\n\n### Declaring an application\n\nEach application is declared as an `application` resource. They are identified by a unique `title`, an `application` name, an `environment` name and a `path`:\n\n```puppet\napplication { 'acme':\n  application =\u003e 'acme',\n  environment =\u003e 'production',\n  path        =\u003e '/opt/acme',\n}\n```\n\nOn disc, this will result in this directory hierarchy (assuming 3 deployments are created: `d1`, `d2`, `d3`):\n\n```\n/opt/acme/\n|-\u003e current@ -\u003e /opt/acme/d3\n|-\u003e d1/\n|-\u003e d2/\n`-\u003e d3/\n```\n\nYour profile is likely to declare an `application` resource and additional resources that make it useful and point in the `current` directory:\n\n```puppet\nclass profile::acme {\n  application { 'acme':\n    application =\u003e 'acme',\n    environment =\u003e 'production',\n    path        =\u003e '/opt/acme',\n  }\n\n  file { '/usr/local/bin/acme-runner':\n    ensure =\u003e link,\n    target =\u003e '/opt/acme/current/bin/acme-runner',\n  }\n\n  apache::vhost { 'acme.example.com':\n    docroot =\u003e '/opt/acme/current/public',\n  }\n}\n```\n\n### mtree integration\n\nSometimes, some data must persist through deployments (e.g. uploaded files, logs).  The application module install the [mtree](https://rubygems.org/gems/mtree) gem to manage symbolic links in the deployments directory and have them point to a `persistent-data` directory if a `.mtree` file is found at the root of a deployment.\n\nAssuming a `.mtree` file is added at the root of the previous project containing:\n\n```\n/set type=dir uname=deploy gname=deploy mode=0755\n.\n\tdb uname=user\n\t\tproduction.sqlite3 type=file uname=user mode=0640\n\t\t..\n\t..\n\tconfig\n\t\tdatabase.yml type=file gname=user mode=0640\n\t\t..\n\t..\n\tlog\n\t\tproduction.log type=file gname=user mode=0660\n\t\t..\n\t..\n\ttmp uname=user gname=user\n\t..\n..\n```\n\nOn the next deployment `d4`, the described hierarchy tree will be created in the `persistent-data` directory, and all files corresponding to leaves of this tree in the deployment will be removed and replaced by symbolic-links to the corresponding persistent-data file:\n\n```\n/opt/acme/\n|-\u003e current@ -\u003e /opt/acme/d4\n|-\u003e d1/\n|-\u003e d2/\n|-\u003e d3/\n|-\u003e d4/\n|   |-\u003e db/\n|   |   `-\u003e production.sqlite3@ -\u003e /opt/acme/persistent-data/db/production.sqlite3\n|   |-\u003e config/\n|   |   `-\u003e database.yml@ -\u003e /opt/acme/persistent-data/config/database.yml\n|   |-\u003e log/\n|   |   `-\u003e production.log@ -\u003e /opt/acme/persistent-data/log/production.log\n|   `-\u003e tmp@ -\u003e /opt/acme/persistent-data/tmp/\n`-\u003e persistent-data/\n    |-\u003e db/\n    |   `-\u003e production.sqlite3\n    |-\u003e config/\n    |   `-\u003e database.yml\n    |-\u003e log/\n    |   `-\u003e production.log\n    `-\u003e tmp/\n```\n\n### Hooks\n\nActions that must be performed before / after deployment and activation can be registered in hooks that can be shared by multiple applications.  Before hooks can abort an operation by exiting with a non-null exit code.\n\nAs an example, one may want to use the following to deploy [Ruby on Rails](https://rubyonrails.org/) applications:\n\n```puppet\napplication::kind { 'rails':\n  before_activate =\u003e @(SH),\n    #!/bin/sh\n\n    set -e\n\n    RAILS_ENV=$ENVIRONMENT bundle exec rails db:migrate\n    | SH\n  after_activate  =\u003e @(SH),\n    #!/bin/sh\n    touch tmp/restart.txt\n    | SH\n}\n\napplication { 'website':\n  # ...\n  kind =\u003e 'rails',\n}\n```\n\n### Continuous Deployment (CD)\n\nThe goal of this module is to allow building custom CD using GitLab and Choria.  The [misc](https://github.com/opus-codium/puppet-application/tree/main/misc) directory features templates to help setup a CD container.  This allows you to rely on [GitLab Generic Packages Repository](https://docs.gitlab.com/ee/user/packages/generic_packages/) to push the packages you build and deploy them using short lived CI/CD job tokens.  The following example build and deploy a new version of an application each time a new tag is pushed:\n\n```yaml\nvariables:\n  URL: \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/artifact.tar.gz\"\n\npackage:\n  stage: package\n  only:\n    - tags\n  script:\n    - tar zcf /tmp/artifact.tar.gz --exclude .git .\n    - curl --fail --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file /tmp/artifact.tar.gz \"${URL}\"'\n\ndeploy:\n  stage: deploy\n  only:\n    - tags\n  needs:\n    - package\n  image:\n    name: registry.example.com/image-builder/mco\n  script: 'mco tasks run application::deploy --application=${CI_PROJECT_NAME} --environment=production --url=\"${URL}\" --deployment_name=\"${CI_COMMIT_TAG}\" --header=\"{\\\"JOB-TOKEN\\\": \\\"${CI_JOB_TOKEN}\\\"}\" -C profile::${CI_PROJECT_NAME}'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopus-codium%2Fpuppet-application","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopus-codium%2Fpuppet-application","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopus-codium%2Fpuppet-application/lists"}