From 3a771dfadd6df25461516faed8116d9fec45ad84 Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Mon, 23 Jan 2023 08:16:01 -0500 Subject: [PATCH 1/6] Fixes #39 Ignore dependency charts directory --- .gitignore | 3 ++- helm-charts/vmpooler/charts/redis-16.10.1.tgz | Bin 88052 -> 0 bytes 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 helm-charts/vmpooler/charts/redis-16.10.1.tgz diff --git a/.gitignore b/.gitignore index 925ecf3..f86fe23 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /*/**/vendor/bundle/ /docker/**/vmpooler.yaml .vagrant/ -.idea/ \ No newline at end of file +.idea/ +helm-charts/vmpooler/charts/ diff --git a/helm-charts/vmpooler/charts/redis-16.10.1.tgz b/helm-charts/vmpooler/charts/redis-16.10.1.tgz deleted file mode 100644 index dfb1e8dfdc3dd4840995329196a238fffd6cee5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88052 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[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 z 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 From 71b4edcd1de64da38f0d7d37272437e092ebfb9c Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Mon, 23 Jan 2023 17:15:18 -0500 Subject: [PATCH 2/6] Consolidate dockerfiles and add docs for development This will reduce the number of files that need to be managed and dependencies that need updated at the same time. --- .github/dependabot.yml | 32 +-- .gitignore | 3 + README.md | 101 +++++++- build-chart.sh | 4 + docker/.dockerignore | 6 + docker/{prod-all-providers => }/Dockerfile | 5 +- docker/Dockerfile.local | 43 ++++ docker/Gemfile | 12 + docker/Gemfile.local | 6 + docker/{prod-all-providers => }/Gemfile.lock | 0 docker/data/redis/.gitkeep | 0 docker/data/vmpooler.yaml | 37 +++ docker/dev/.dockerignore | 3 - docker/dev/Dockerfile | 38 ---- docker/dev/Dockerfile-aio | 39 ---- docker/dev/docker-compose.yml | 71 ------ docker/docker-compose.local.yml | 79 +++++++ docker/docker-compose.yml | 89 ++++++++ docker/{dev => }/docker-entrypoint.sh | 0 docker/prod-all-providers/.bundle/config | 2 - docker/prod-all-providers/.dockerignore | 3 - docker/prod-all-providers/Gemfile | 6 - docker/prod-all-providers/docker-compose.yml | 71 ------ .../prod-all-providers/docker-entrypoint.sh | 6 - .../prod-all-providers/update-gemfile-lock.sh | 6 - docker/test-all-providers/.bundle/config | 2 - docker/test-all-providers/.dockerignore | 3 - docker/test-all-providers/Dockerfile | 38 ---- docker/test-all-providers/Gemfile | 7 - docker/test-all-providers/Gemfile.lock | 215 ------------------ docker/test-all-providers/docker-compose.yml | 71 ------ .../test-all-providers/docker-entrypoint.sh | 6 - ...te-gemfile-lock.sh => update-gemfile-lock} | 0 update-changelog | 5 + update-chart-lock | 4 + 35 files changed, 386 insertions(+), 627 deletions(-) create mode 100755 build-chart.sh create mode 100644 docker/.dockerignore rename docker/{prod-all-providers => }/Dockerfile (92%) create mode 100644 docker/Dockerfile.local create mode 100644 docker/Gemfile create mode 100644 docker/Gemfile.local rename docker/{prod-all-providers => }/Gemfile.lock (100%) create mode 100644 docker/data/redis/.gitkeep create mode 100644 docker/data/vmpooler.yaml delete mode 100644 docker/dev/.dockerignore delete mode 100644 docker/dev/Dockerfile delete mode 100644 docker/dev/Dockerfile-aio delete mode 100644 docker/dev/docker-compose.yml create mode 100644 docker/docker-compose.local.yml create mode 100644 docker/docker-compose.yml rename docker/{dev => }/docker-entrypoint.sh (100%) delete mode 100644 docker/prod-all-providers/.bundle/config delete mode 100644 docker/prod-all-providers/.dockerignore delete mode 100644 docker/prod-all-providers/Gemfile delete mode 100644 docker/prod-all-providers/docker-compose.yml delete mode 100644 docker/prod-all-providers/docker-entrypoint.sh delete mode 100755 docker/prod-all-providers/update-gemfile-lock.sh delete mode 100644 docker/test-all-providers/.bundle/config delete mode 100644 docker/test-all-providers/.dockerignore delete mode 100644 docker/test-all-providers/Dockerfile delete mode 100644 docker/test-all-providers/Gemfile delete mode 100644 docker/test-all-providers/Gemfile.lock delete mode 100644 docker/test-all-providers/docker-compose.yml delete mode 100644 docker/test-all-providers/docker-entrypoint.sh rename docker/{test-all-providers/update-gemfile-lock.sh => update-gemfile-lock} (100%) create mode 100755 update-changelog create mode 100755 update-chart-lock diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d228804..76020ad 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,35 +1,13 @@ version: 2 updates: -# /docker/dev folder - package-ecosystem: docker - directory: "/docker/dev/" + directory: "/docker/" schedule: - interval: daily - time: "13:00" + interval: weekly open-pull-requests-limit: 10 -# /docker/prod-all-providers folder + - package-ecosystem: bundler - directory: "/docker/prod-all-providers/" + directory: "/docker/" schedule: - interval: daily - time: "13:00" - open-pull-requests-limit: 10 -- package-ecosystem: docker - directory: "/docker/prod-all-providers/" - schedule: - interval: daily - time: "13:00" - open-pull-requests-limit: 10 -# /docker/test-all-providers folder -- package-ecosystem: bundler - directory: "/docker/test-all-providers/" - schedule: - interval: daily - time: "13:00" - open-pull-requests-limit: 10 -- package-ecosystem: docker - directory: "/docker/test-all-providers/" - schedule: - interval: daily - time: "13:00" + interval: weekly open-pull-requests-limit: 10 diff --git a/.gitignore b/.gitignore index f86fe23..ba34006 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ .vagrant/ .idea/ helm-charts/vmpooler/charts/ +/docker/data/redis/** +!docker/data/**/*.yaml +!docker/data/**/.gitkeep \ No newline at end of file diff --git a/README.md b/README.md index d15f5e2..7bf0423 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,35 @@ # vmpooler-deployment +- [vmpooler-deployment](#vmpooler-deployment) + - [VMPooler Components](#vmpooler-components) + - [Docker Registry](#docker-registry) + - [Helm Repository](#helm-repository) + - [Adding / updating charts](#adding--updating-charts) + - [Development](#development) + - [Docker Compose URLs](#docker-compose-urls) + - [Deploy Chart for Testing](#deploy-chart-for-testing) + - [Releasing](#releasing) + - [Contributing](#contributing) + - [License](#license) + This repo contains Dockerfiles and a Helm chart that can be used to deploy [VMPooler](https://github.com/puppetlabs/vmpooler). The Release Engineering team at Puppet uses the code here as part of operating our VMPooler instances. +## VMPooler Components + +The docker image gnerated and hosted by this project contain the following VMPooler components: + +- [VMPooler Core](https://github.com/puppetlabs/vmpooler) +- [VMPooler EC2 Provider](https://github.com/puppetlabs/vmpooler-provider-ec2) +- [VMPooler GCE Provider](https://github.com/puppetlabs/vmpooler-provider-gce) +- [VMPooler vSphere Provider](https://github.com/puppetlabs/vmpooler-provider-vsphere) + ## Docker Registry The GitHub Actions in this repository publish images to GitHub Packages. You can browse the VMPooler containers [here](https://github.com/puppetlabs/vmpooler-deployment/pkgs/container/vmpooler-deployment%2Fvmpooler). -Containers are organized using image tags: +The vmpooler officially released docker image tags use a semantic version, where the version increments correlate to the increments in any of the gems at `docker/Gemfile`. -- `x.y.z-prod-all-providers` represents images built using the Dockerfile in `docker/prod-all-providers`. These images use the Gemfile in the same directory to pull in current versions of the `vmpooler` gem and the gems for all known production-grade providers. +Image tags starting with `pr-` are generated when opening and pushing to a pull request and will periodically be cleaned up. ## Helm Repository @@ -21,14 +42,74 @@ $ helm repo add vmpooler-deployment https://puppetlabs.github.io/vmpooler-deploy ### Adding / updating charts -```bash -cd docs/ -helm package ../helm-charts/* -helm repo index --url https://puppetlabs.github.io/vmpooler-deployment/ . -git add . -cd .. -git commit -a -``` +Make the desired changes to the helm chart in helm-charts/vmpooler and run `./update-chart`. + +## Development + +Prerequisites: + +- [Docker](https://docs.docker.com/engine/install/) +- [Docker Compose](https://docs.docker.com/compose/install/) + +1. Become familiar with the configuration file `docker/vmpooler.yaml` as described in [VMPooler](https://github.com/puppetlabs/vmpooler) Core. + - The default configuration file only enables the dummy provider built into [VMPooler](https://github.com/puppetlabs/vmpooler) Core. See each project below for documentation on how to use provider specific options: + - [vmpooler-provider-ec2](https://github.com/puppetlabs/vmpooler-provider-ec2) + - [vmpooler-provider-gce](https://github.com/puppetlabs/vmpooler-provider-gce) + - [vmpooler-provider-vsphere](https://github.com/puppetlabs/vmpooler-provider-vsphere) +2. Chose a Development method: + - Develop via local source: + 1. Clone all of the known vmpooler projects listed at [vmpooler-components](#vmpooler-components) under a common directory, for example: + + ```bash + |-- vmpooler-projects + | |--vmpooler-deployment + | |--vmpooler-provider-ec2 + | |--vmpooler-provider-gce + | |--vmpooler-provider-vsphere + ``` + + 2. From the `vmpooler-projects` directory run `docker build -t vmpooler-local -f vmpooler-deployment/docker/Dockerfile.local .` + 3. Run `docker compose -f vmpooler-deployment/docker/docker-compose.local.yml up` + + - Develop via Git source: + 1. For the component(s) you are developing on, commit and push changes to a branch. + 2. Change to the `docker` directory and modify the `Gemfile` as needed to pull the gem(s) from your git branch. + 3. Run `./update-gemfile-lock` to update the `Gemfile.lock` + 4. Run `docker compose build && docker compose up`. + +When a dependency Helm chart is updated, be sure to run `./update-chart-lock` to update the lockfile, otherwise the test and release workflows will fail. + +### Docker Compose URLs + +These are the default ports used in the docker compose file, to change them edit the `ports` key under the desired service in either `docker/docker-compose.yml` or `docker/docker-compose.local.yml`. + +| App/Endpoint | Path | +|--------------------|-------------------------------------------------------------| +| Redis Server | `localhost:6379` (Password: `vmpooler`) | +| Redis Commander | (Credentials: `admin:admin`) | +| Jaeger | +| VMPooler API | | +| VMPooler Dashboard | | +| Metrics (API) | | +| Metrics (Manager) | | + +### Deploy Chart for Testing + +Helm charts are hosted with GitHub Pages since GitHub Packages does not support Helm, so you will need to build the chart locally and push the chart to your own helm repository. Follow these steps to generate a chart to host internally: + +1. Update the "appVersion" key in `helm-charts/vmpooler/Chart.yaml` to the docker image tag that was generated by opening a pull request. +2. Update the "version" key to a pre-release tag, something like "x.y.z-rc.1", then run `./build-chart` to build the chart locally, and upload it to your desired location. + +## Releasing + +Create a GitHub tag and release, publish a new docker image, and helm chart by opening a release prep pull request and running the release action: + +1. Bump the "appVersion" key in `helm-charts/vmpooler/Chart.yaml` appropriately based on changes to `docker/Gemfile` abd `docker/Gemfile.lock` in merged pull requests since the last release. +2. Bump the "version" key in `helm-charts/vmpooler/Chart.yaml` appropriately based on changes to the chart itself and increments of the "appVersion" in merged pull requests since the last release. +3. Run `./update-changelog` to update `CHANGELOG.md`. +4. Commit and push changes to a new branch, then open a pull request against `main` and be sure to add the "maintenance" label. +5. After the pull request is approved and merged, then navigate to Actions --> Docker and Helm Release --> run workflow --> Branch: main --> Run workflow. + - This action will push a tagged docker image to the GitHub container registry and helm chart to GitHub pages. ## Contributing diff --git a/build-chart.sh b/build-chart.sh new file mode 100755 index 0000000..ffe8010 --- /dev/null +++ b/build-chart.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +docker run --rm -it -v $(pwd):/apps --entrypoint /bin/sh alpine/helm \ + -c 'helm repo add bitnami https://charts.bitnami.com/bitnami && cd /apps/helm-charts/vmpooler && helm dependency update && cd /apps/docs && helm package ../helm-charts/* && helm repo index --url https://puppetlabs.github.io/vmpooler-deployment/ .' diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000..5052e88 --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1,6 @@ +# Exclude everything by default; explicitly include necessary files +* +!Gemfile +!Gemfile.lock +!Gemfile.local +!docker-entrypoint.sh diff --git a/docker/prod-all-providers/Dockerfile b/docker/Dockerfile similarity index 92% rename from docker/prod-all-providers/Dockerfile rename to docker/Dockerfile index 1cb1d50..14ec768 100644 --- a/docker/prod-all-providers/Dockerfile +++ b/docker/Dockerfile @@ -8,7 +8,7 @@ # RUN: # docker run -e VMPOOLER_CONFIG -p 80:4567 -it vmpooler -FROM jruby:9.3.6-jdk +FROM amd64/jruby:9.3.6-jdk LABEL org.opencontainers.image.description "VMPooler plus all known providers" @@ -23,8 +23,7 @@ RUN apt-get update -qq && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* -RUN gem install bundler && \ - gem update --system 3.2.3 +RUN gem install bundler COPY ./docker-entrypoint.sh /usr/local/bin/ diff --git a/docker/Dockerfile.local b/docker/Dockerfile.local new file mode 100644 index 0000000..970cefe --- /dev/null +++ b/docker/Dockerfile.local @@ -0,0 +1,43 @@ +# For local development of vmpooler core and provider gems instead of using a +# git source ensure the following directory structure: +# |-- vmpooler-projects +# | |--vmpooler-deployment +# | |--vmpooler-provider-ec2 +# | |--vmpooler-provider-gce +# | |--vmpooler-provider-vsphere +# +# Then change directory into vmpooler-projects and build with: + + +FROM amd64/jruby:9.3.6-jdk + +LABEL org.opencontainers.image.description "VMPooler plus all known providers" + +ENV DEBIAN_FRONTEND=noninteractive +ENV LOGFILE=/dev/stdout +ENV RACK_ENV=production + +RUN apt-get update -qq && \ + apt-get upgrade -y && \ + apt-get install -y --no-install-recommends make git netbase && \ + apt-get clean autoclean && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/* + +COPY vmpooler /opt/vmpooler +COPY vmpooler-provider-ec2 /opt/vmpooler-provider-ec2 +COPY vmpooler-provider-gce /opt/vmpooler-provider-gce +COPY vmpooler-provider-vsphere /opt/vmpooler-provider-vsphere + +RUN gem install bundler + +COPY vmpooler-deployment/docker/docker-entrypoint.sh /usr/local/bin/ + +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +COPY vmpooler-deployment/docker/Gemfile.local ./Gemfile + +RUN bundle config set --local jobs 3 && \ + bundle install + +ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/docker/Gemfile b/docker/Gemfile new file mode 100644 index 0000000..9bfbe83 --- /dev/null +++ b/docker/Gemfile @@ -0,0 +1,12 @@ +source ENV['GEM_SOURCE'] || 'https://rubygems.org' + +gem 'vmpooler', '~> 2.4' +gem 'vmpooler-provider-ec2', '~> 0.0.1' +gem 'vmpooler-provider-gce', '~> 0.4' +gem 'vmpooler-provider-vsphere', '~> 1.6' + +# For development install via a git branch use something like: +# gem 'vmpooler', git: 'https://github.com/puppetlabs/vmpooler.git', branch: 'my-feature' +# gem 'vmpooler-provider-ec2', git: 'https://github.com/puppetlabs/vmpooler-provider-ec2.git', branch: 'my-feature' +# gem 'vmpooler-provider-gce', git: 'https://github.com/puppetlabs/vmpooler-provider-gce.git', branch: 'my-feature' +# gem 'vmpooler-provider-vsphere', git: 'https://github.com/puppetlabs/vmpooler-provider-vsphere.git', branch: 'my-feature' diff --git a/docker/Gemfile.local b/docker/Gemfile.local new file mode 100644 index 0000000..5ba111f --- /dev/null +++ b/docker/Gemfile.local @@ -0,0 +1,6 @@ +source ENV['GEM_SOURCE'] || 'https://rubygems.org' + +gem 'vmpooler', path: '/opt/vmpooler' +gem 'vmpooler-provider-ec2', path: '/opt/vmpooler-provider-ec2' +gem 'vmpooler-provider-gce', path: '/opt/vmpooler-provider-gce' +gem 'vmpooler-provider-vsphere', path: '/opt/vmpooler-provider-vsphere' \ No newline at end of file diff --git a/docker/prod-all-providers/Gemfile.lock b/docker/Gemfile.lock similarity index 100% rename from docker/prod-all-providers/Gemfile.lock rename to docker/Gemfile.lock diff --git a/docker/data/redis/.gitkeep b/docker/data/redis/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker/data/vmpooler.yaml b/docker/data/vmpooler.yaml new file mode 100644 index 0000000..4238587 --- /dev/null +++ b/docker/data/vmpooler.yaml @@ -0,0 +1,37 @@ +--- +:providers: + :dummy: + filename: '/tmp/dummy-backing.yaml' + +:prometheus: + prefix: 'vmpooler-local' + +:redis: + server: 'redis-server' + +:auth: + provider: 'dummy' + +:config: + site_name: 'vmpooler' + logfile: '/var/log/vmpooler.log' + task_limit: 10 + timeout: 15 + vm_checktime: 1 + vm_lifetime: 12 + vm_lifetime_auth: 24 + allowed_tags: + - 'created_by' + - 'project' + domain: 'example.com' + # domain: 'localhost' # Flip these out for local requests + +:pools: + - name: 'debian-10-x86_64' + template: 'Templates/debian-7-x86_64' + folder: 'Pooled VMs/debian-7-x86_64' + datastore: 'vmstorage' + size: 5 + timeout: 15 + ready_ttl: 1440 + provider: dummy diff --git a/docker/dev/.dockerignore b/docker/dev/.dockerignore deleted file mode 100644 index 8dad93e..0000000 --- a/docker/dev/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.bundle/ -vendor/ -update-gemfile-lock.sh diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile deleted file mode 100644 index ffea807..0000000 --- a/docker/dev/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -# Run vmpooler in a Docker container! Configuration can either be embedded -# and built within the current working directory, or stored in a -# VMPOOLER_CONFIG environment value and passed to the Docker daemon. -# -# BUILD: -# docker build -t vmpooler . -# -# RUN: -# docker run -e VMPOOLER_CONFIG -p 80:4567 -it vmpooler - -FROM jruby:9.3.6-jdk - -ENV DEBIAN_FRONTEND=noninteractive -ENV RACK_ENV=production - -RUN apt-get update -qq && \ - apt-get upgrade -y && \ - apt-get install -y --no-install-recommends make git netbase && \ - apt-get clean autoclean && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/* - -COPY docker/docker-entrypoint.sh /usr/local/bin/ -COPY ./Gemfile ./ -COPY ./vmpooler.gemspec ./ -COPY ./lib/vmpooler/version.rb ./lib/vmpooler/version.rb - -RUN gem install bundler && \ - bundle config set --local jobs 3 && \ - bundle install - -COPY ./ ./ - -RUN gem build vmpooler.gemspec && \ - gem install vmpooler*.gem && \ - chmod +x /usr/local/bin/docker-entrypoint.sh - -ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/docker/dev/Dockerfile-aio b/docker/dev/Dockerfile-aio deleted file mode 100644 index 2401e5d..0000000 --- a/docker/dev/Dockerfile-aio +++ /dev/null @@ -1,39 +0,0 @@ -# Run vmpooler in a Docker container! Configuration can either be embedded -# and built within the current working directory, or stored in a -# VMPOOLER_CONFIG environment value and passed to the Docker daemon. -# -# BUILD: -# docker build -t vmpooler . -# -# RUN: -# docker run -e VMPOOLER_CONFIG -p 80:4567 -it vmpooler - -FROM jruby:9.3.6-jdk - -RUN mkdir -p /var/lib/vmpooler - -WORKDIR /var/lib/vmpooler - -RUN echo "deb http://httpredir.debian.org/debian jessie main" >/etc/apt/sources.list.d/jessie-main.list - -RUN apt-get update -qq && \ - apt-get install -y --no-install-recommends make git redis-server && \ - apt-get clean autoclean && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/* - -ADD Gemfile* /var/lib/vmpooler/ - -RUN bundle install --system - -RUN ln -s /opt/jruby/bin/jruby /usr/bin/jruby - -COPY . /var/lib/vmpooler - -ENV VMPOOLER_LOG /var/log/vmpooler.log - -CMD \ - /etc/init.d/redis-server start \ - && /var/lib/vmpooler/scripts/vmpooler_init.sh start \ - && while [ ! -f ${VMPOOLER_LOG} ]; do sleep 1; done ; \ - tail -f ${VMPOOLER_LOG} diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml deleted file mode 100644 index 404deff..0000000 --- a/docker/dev/docker-compose.yml +++ /dev/null @@ -1,71 +0,0 @@ -# For local development run with a dummy provider -version: '3.8' -services: - vmpooler-api: - build: - context: ../ - dockerfile: docker/Dockerfile_local - volumes: - - type: bind - source: ${PWD}/vmpooler.yaml - target: /etc/vmpooler/vmpooler.yaml - ports: - - "8080:4567" - networks: - - redis-net - environment: - - VMPOOLER_DEBUG=true # for use of dummy auth - - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml - - REDIS_SERVER=redislocal - - LOGFILE=/dev/null - - VMPOOLER_TRACING_ENABLED=true - - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces - image: vmpooler-local - command: api - depends_on: - - redislocal - vmpooler-manager: - build: - context: ../ - dockerfile: docker/Dockerfile_local - volumes: - - type: bind - source: ${PWD}/vmpooler.yaml - target: /etc/vmpooler/vmpooler.yaml - ports: - - "8081:4567" - networks: - - redis-net - environment: - - VMPOOLER_DEBUG=true # for use of dummy auth - - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml - - REDIS_SERVER=redislocal - - LOGFILE=/dev/null - - VMPOOLER_TRACING_ENABLED=true - - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces - image: vmpooler-local - command: manager - depends_on: - - redislocal - redislocal: - image: redis - # Uncomment this if you don't want the redis data to persist - #command: "redis-server --save '' --appendonly no" - ports: - - "6379:6379" - networks: - - redis-net - jaeger-aio: - image: jaegertracing/all-in-one:1.18 - ports: - - "14250:14250" - - "8082:16686" - networks: - - redis-net - user: '1001' - read_only: true - cap_drop: - - ALL - -networks: - redis-net: diff --git a/docker/docker-compose.local.yml b/docker/docker-compose.local.yml new file mode 100644 index 0000000..f5788bf --- /dev/null +++ b/docker/docker-compose.local.yml @@ -0,0 +1,79 @@ +# For local development run with a dummy provider +version: '3.8' +services: + redis-server: + # This should match the major version used in the vmpooler helm chart + image: redis:6 + command: "redis-server --requirepass vmpooler" + volumes: + - type: bind + source: ./data/redis + target: /data + ports: + - "6379:6379" + + redis-commander: + image: rediscommander/redis-commander:latest + environment: + - REDIS_HOST=redis-server + - REDIS_PASSWORD=vmpooler + - HTTP_USER=admin + - HTTP_PASSWORD=admin + ports: + - 8080:8081 + links: + - redis-server + + jaeger-aio: + image: jaegertracing/all-in-one:1 + ports: + - "14250:14250" + - "8081:16686" + user: '1001' + read_only: true + cap_drop: + - ALL + + vmpooler-api: + # See image build instructions in README and Dockerfile.local + image: vmpooler-local + volumes: + - type: bind + source: ./data/vmpooler.yaml + target: /etc/vmpooler/vmpooler.yaml + ports: + - "8082:4567" + environment: + - VMPOOLER_DEBUG=true # for use of dummy auth + - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml + - REDIS_SERVER=redis-server + - REDIS_PASSWORD=vmpooler + - LOGFILE=/dev/null + - VMPOOLER_TRACING_ENABLED=true + - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces + command: api + links: + - redis-server + - jaeger-aio + + vmpooler-manager: + # See image build instructions in README and Dockerfile.local + image: vmpooler-local + volumes: + - type: bind + source: ./data/vmpooler.yaml + target: /etc/vmpooler/vmpooler.yaml + ports: + - "8083:4567" + environment: + - VMPOOLER_DEBUG=true # for use of dummy auth + - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml + - REDIS_SERVER=redis-server + - REDIS_PASSWORD=vmpooler + - LOGFILE=/dev/null + - VMPOOLER_TRACING_ENABLED=true + - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces + command: manager + links: + - redis-server + - jaeger-aio diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..3a81546 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,89 @@ +# For local development run with a dummy provider +version: '3.8' +services: + redis-server: + # This should match the major version used in the vmpooler helm chart + image: redis:6 + command: "redis-server --requirepass vmpooler" + volumes: + - type: bind + source: ./data/redis + target: /data + ports: + - "6379:6379" + + redis-commander: + image: rediscommander/redis-commander:latest + environment: + - REDIS_HOST=redis-server + - REDIS_PASSWORD=vmpooler + - HTTP_USER=admin + - HTTP_PASSWORD=admin + ports: + - 8080:8081 + links: + - redis-server + + jaeger-aio: + image: jaegertracing/all-in-one:1 + ports: + - "14250:14250" + - "8081:16686" + user: '1001' + read_only: true + cap_drop: + - ALL + + vmpooler-api: + # Uncomment image and comment out build, which will allow you to use an + # image with local gem source instead of from a git source. + # See build instructions in Dockerfile.local + # image: vmpooler-local + build: + context: ./ + dockerfile: Dockerfile + volumes: + - type: bind + source: ./data/vmpooler.yaml + target: /etc/vmpooler/vmpooler.yaml + ports: + - "8082:4567" + environment: + - VMPOOLER_DEBUG=true # for use of dummy auth + - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml + - REDIS_SERVER=redis-server + - REDIS_PASSWORD=vmpooler + - LOGFILE=/dev/null + - VMPOOLER_TRACING_ENABLED=true + - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces + command: api + links: + - redis-server + - jaeger-aio + + vmpooler-manager: + # Uncomment image and comment out build, which will allow you to use an + # image with local gem source instead of from a git source. + # See build instructions in Dockerfile.local + # image: vmpooler-local + build: + context: ./ + dockerfile: Dockerfile + volumes: + - type: bind + source: ./data/vmpooler.yaml + target: /etc/vmpooler/vmpooler.yaml + ports: + - "8083:4567" + environment: + - VMPOOLER_DEBUG=true # for use of dummy auth + - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml + - REDIS_SERVER=redis-server + - REDIS_PASSWORD=vmpooler + - LOGFILE=/dev/null + - VMPOOLER_TRACING_ENABLED=true + - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces + command: manager + links: + - redis-server + - jaeger-aio diff --git a/docker/dev/docker-entrypoint.sh b/docker/docker-entrypoint.sh similarity index 100% rename from docker/dev/docker-entrypoint.sh rename to docker/docker-entrypoint.sh diff --git a/docker/prod-all-providers/.bundle/config b/docker/prod-all-providers/.bundle/config deleted file mode 100644 index 2369228..0000000 --- a/docker/prod-all-providers/.bundle/config +++ /dev/null @@ -1,2 +0,0 @@ ---- -BUNDLE_PATH: "vendor/bundle" diff --git a/docker/prod-all-providers/.dockerignore b/docker/prod-all-providers/.dockerignore deleted file mode 100644 index 8dad93e..0000000 --- a/docker/prod-all-providers/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.bundle/ -vendor/ -update-gemfile-lock.sh diff --git a/docker/prod-all-providers/Gemfile b/docker/prod-all-providers/Gemfile deleted file mode 100644 index 688d20e..0000000 --- a/docker/prod-all-providers/Gemfile +++ /dev/null @@ -1,6 +0,0 @@ -source ENV['GEM_SOURCE'] || 'https://rubygems.org' - -gem 'vmpooler', '~> 2.4' -gem 'vmpooler-provider-ec2', '~> 0.0.1' -gem 'vmpooler-provider-gce', '~> 0.4' -gem 'vmpooler-provider-vsphere', '~> 1.6' diff --git a/docker/prod-all-providers/docker-compose.yml b/docker/prod-all-providers/docker-compose.yml deleted file mode 100644 index d93a8bb..0000000 --- a/docker/prod-all-providers/docker-compose.yml +++ /dev/null @@ -1,71 +0,0 @@ -# For local development run with a dummy provider -version: '3.8' -services: - vmpooler-api: - build: - context: ./ - dockerfile: Dockerfile - volumes: - - type: bind - source: ${PWD}/vmpooler.yaml - target: /etc/vmpooler/vmpooler.yaml - ports: - - "8080:4567" - networks: - - redis-net - environment: - - VMPOOLER_DEBUG=true # for use of dummy auth - - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml - - REDIS_SERVER=redislocal - - LOGFILE=/dev/null - - VMPOOLER_TRACING_ENABLED=true - - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces - image: vmpooler-local - command: api - depends_on: - - redislocal - vmpooler-manager: - build: - context: ./ - dockerfile: Dockerfile - volumes: - - type: bind - source: ${PWD}/vmpooler.yaml - target: /etc/vmpooler/vmpooler.yaml - ports: - - "8081:4567" - networks: - - redis-net - environment: - - VMPOOLER_DEBUG=true # for use of dummy auth - - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml - - REDIS_SERVER=redislocal - - LOGFILE=/dev/null - - VMPOOLER_TRACING_ENABLED=true - - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces - image: vmpooler-local - command: manager - depends_on: - - redislocal - redislocal: - image: redis - # Uncomment this if you don't want the redis data to persist - #command: "redis-server --save '' --appendonly no" - ports: - - "6379:6379" - networks: - - redis-net - jaeger-aio: - image: jaegertracing/all-in-one:1.18 - ports: - - "14250:14250" - - "8082:16686" - networks: - - redis-net - user: '1001' - read_only: true - cap_drop: - - ALL - -networks: - redis-net: diff --git a/docker/prod-all-providers/docker-entrypoint.sh b/docker/prod-all-providers/docker-entrypoint.sh deleted file mode 100644 index 07d11de..0000000 --- a/docker/prod-all-providers/docker-entrypoint.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -e - -set -- bundle exec vmpooler "$@" - -exec "$@" diff --git a/docker/prod-all-providers/update-gemfile-lock.sh b/docker/prod-all-providers/update-gemfile-lock.sh deleted file mode 100755 index 14eadf5..0000000 --- a/docker/prod-all-providers/update-gemfile-lock.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -docker run -it --rm \ - -v $(pwd):/app \ - $(grep ^FROM ./Dockerfile |cut -d ' ' -f2) \ - /bin/bash -c 'apt-get update -qq && apt-get install -y --no-install-recommends make git && cd /app && gem install bundler && gem update --system 3.2.3 && bundle install --jobs 3 && bundle update; echo "LOCK_FILE_UPDATE_EXIT_CODE=$?"' diff --git a/docker/test-all-providers/.bundle/config b/docker/test-all-providers/.bundle/config deleted file mode 100644 index 2369228..0000000 --- a/docker/test-all-providers/.bundle/config +++ /dev/null @@ -1,2 +0,0 @@ ---- -BUNDLE_PATH: "vendor/bundle" diff --git a/docker/test-all-providers/.dockerignore b/docker/test-all-providers/.dockerignore deleted file mode 100644 index 8dad93e..0000000 --- a/docker/test-all-providers/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.bundle/ -vendor/ -update-gemfile-lock.sh diff --git a/docker/test-all-providers/Dockerfile b/docker/test-all-providers/Dockerfile deleted file mode 100644 index 010012a..0000000 --- a/docker/test-all-providers/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -# Run vmpooler in a Docker container! Configuration can either be embedded -# and built within the current working directory, or stored in a -# VMPOOLER_CONFIG environment value and passed to the Docker daemon. -# -# BUILD: -# docker build -t vmpooler . -# -# RUN: -# docker run -e VMPOOLER_CONFIG -p 80:4567 -it vmpooler - -FROM jruby:9.3.6-jdk - -LABEL org.opencontainers.image.description "VMPooler and known providers pulled directly from Git" - -ENV DEBIAN_FRONTEND=noninteractive -ENV LOGFILE=/dev/stdout -ENV RACK_ENV=production - -RUN apt-get update -qq && \ - apt-get upgrade -y && \ - apt-get install -y --no-install-recommends make git netbase && \ - apt-get clean autoclean && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/* - -RUN gem install bundler && \ - gem update --system 3.2.3 - -COPY ./docker-entrypoint.sh /usr/local/bin/ - -RUN chmod +x /usr/local/bin/docker-entrypoint.sh - -COPY ./Gemfile* ./ - -RUN bundle config set --local jobs 3 && \ - bundle install - -ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/docker/test-all-providers/Gemfile b/docker/test-all-providers/Gemfile deleted file mode 100644 index 10d1eb9..0000000 --- a/docker/test-all-providers/Gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source ENV['GEM_SOURCE'] || 'https://rubygems.org' - -gem 'vmpooler', git: 'https://github.com/puppetlabs/vmpooler.git' -gem 'vmpooler-provider-ec2', git: 'https://github.com/puppetlabs/vmpooler-provider-ec2.git' -gem 'vmpooler-provider-gce', git: 'https://github.com/puppetlabs/vmpooler-provider-gce.git' -gem 'vmpooler-provider-vsphere', git: 'https://github.com/puppetlabs/vmpooler-provider-vsphere.git' - diff --git a/docker/test-all-providers/Gemfile.lock b/docker/test-all-providers/Gemfile.lock deleted file mode 100644 index 805c54c..0000000 --- a/docker/test-all-providers/Gemfile.lock +++ /dev/null @@ -1,215 +0,0 @@ -GIT - remote: https://github.com/puppetlabs/vmpooler-provider-ec2.git - revision: 13d0de6dc035c46dcd099d0b5e9b02bc19e8fcdd - specs: - vmpooler-provider-ec2 (0.0.1) - aws-sdk-ec2 (~> 1) - net-ssh (~> 6.2.0.rc2) - -GIT - remote: https://github.com/puppetlabs/vmpooler-provider-gce.git - revision: 46b9c5aef06184f8a2bd0be6086ae2256b19020a - specs: - vmpooler-provider-gce (0.3.0) - google-apis-compute_v1 (~> 0.14) - google-cloud-dns (~> 0.35.1) - googleauth (>= 0.16.2, < 1.2.0) - -GIT - remote: https://github.com/puppetlabs/vmpooler-provider-vsphere.git - revision: 82e35dfb54705f9a495b64498779da6cfb322f16 - specs: - vmpooler-provider-vsphere (1.6.0) - rbvmomi (>= 2.1, < 4.0) - -GIT - remote: https://github.com/puppetlabs/vmpooler.git - revision: b9a1bb74017c417526cde6586b8dd333435ff74c - specs: - vmpooler (2.4.0) - concurrent-ruby (~> 1.1) - connection_pool (~> 2.2) - deep_merge (~> 1.2) - net-ldap (~> 0.16) - opentelemetry-exporter-jaeger (= 0.20.1) - opentelemetry-instrumentation-concurrent_ruby (= 0.19.2) - opentelemetry-instrumentation-http_client (= 0.19.4) - opentelemetry-instrumentation-redis (= 0.21.3) - opentelemetry-instrumentation-sinatra (= 0.19.3) - opentelemetry-resource_detectors (= 0.19.1) - opentelemetry-sdk (~> 1.0, >= 1.0.2) - pickup (~> 0.0.11) - prometheus-client (~> 2.0) - puma (~> 5.0, >= 5.0.4) - rack (~> 2.2) - rake (~> 13.0) - redis (~> 4.1) - sinatra (~> 2.0) - spicy-proton (~> 2.1) - statsd-ruby (~> 1.4) - -GEM - remote: https://rubygems.org/ - specs: - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - aws-eventstream (1.2.0) - aws-partitions (1.610.0) - aws-sdk-core (3.131.3) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.525.0) - aws-sigv4 (~> 1.1) - jmespath (~> 1, >= 1.6.1) - aws-sdk-ec2 (1.324.0) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sigv4 (1.5.1) - aws-eventstream (~> 1, >= 1.0.2) - bindata (2.4.10) - builder (3.2.4) - concurrent-ruby (1.1.10) - connection_pool (2.2.5) - declarative (0.0.20) - deep_merge (1.2.2) - faraday (2.3.0) - faraday-net_http (~> 2.0) - ruby2_keywords (>= 0.0.4) - faraday-net_http (2.0.3) - google-apis-compute_v1 (0.44.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-core (0.7.0) - addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) - httpclient (>= 2.8.1, < 3.a) - mini_mime (~> 1.0) - representable (~> 3.0) - retriable (>= 2.0, < 4.a) - rexml - webrick - google-apis-dns_v1 (0.23.0) - google-apis-core (>= 0.7, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) - google-cloud-errors (~> 1.0) - google-cloud-dns (0.35.1) - google-apis-dns_v1 (~> 0.1) - google-cloud-core (~> 1.6) - googleauth (>= 0.16.2, < 2.a) - zonefile (~> 1.04) - google-cloud-env (1.6.0) - faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.2.0) - googleauth (1.1.3) - faraday (>= 0.17.3, < 3.a) - jwt (>= 1.4, < 3.0) - memoist (~> 0.16) - multi_json (~> 1.11) - os (>= 0.9, < 2.0) - signet (>= 0.16, < 2.a) - httpclient (2.8.3) - jmespath (1.6.1) - json (2.6.2-java) - jwt (2.4.1) - memoist (0.16.2) - mini_mime (1.1.2) - multi_json (1.15.0) - mustermann (2.0.2) - ruby2_keywords (~> 0.0.1) - net-ldap (0.17.1) - net-ssh (6.2.0.rc2) - nio4r (2.5.8-java) - nokogiri (1.13.8-java) - racc (~> 1.4) - opentelemetry-api (1.0.2) - opentelemetry-common (0.19.6) - opentelemetry-api (~> 1.0) - opentelemetry-exporter-jaeger (0.20.1) - opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.19.2) - opentelemetry-sdk (~> 1.0) - thrift - opentelemetry-instrumentation-base (0.19.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-concurrent_ruby (0.19.2) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.19.0) - opentelemetry-instrumentation-http_client (0.19.4) - opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.19.3) - opentelemetry-instrumentation-base (~> 0.19.0) - opentelemetry-instrumentation-redis (0.21.3) - opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.19.3) - opentelemetry-instrumentation-base (~> 0.19.0) - opentelemetry-instrumentation-sinatra (0.19.3) - opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.19.3) - opentelemetry-instrumentation-base (~> 0.19.0) - opentelemetry-registry (0.1.0) - opentelemetry-api (~> 1.0.1) - opentelemetry-resource_detectors (0.19.1) - google-cloud-env - opentelemetry-sdk - opentelemetry-sdk (1.1.0) - opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.19.3) - opentelemetry-registry (~> 0.1) - opentelemetry-semantic_conventions - opentelemetry-semantic_conventions (1.8.0) - opentelemetry-api (~> 1.0) - optimist (3.0.1) - os (1.1.4) - pickup (0.0.11) - prometheus-client (2.1.0) - public_suffix (4.0.7) - puma (5.6.4-java) - nio4r (~> 2.0) - racc (1.6.0-java) - rack (2.2.4) - rack-protection (2.2.2) - rack - rake (13.0.6) - rbvmomi (3.0.0) - builder (~> 3.2) - json (~> 2.3) - nokogiri (~> 1.10) - optimist (~> 3.0) - redis (4.7.1) - representable (3.2.0) - declarative (< 0.1.0) - trailblazer-option (>= 0.1.1, < 0.2.0) - uber (< 0.2.0) - retriable (3.1.2) - rexml (3.2.5) - ruby2_keywords (0.0.5) - signet (0.17.0) - addressable (~> 2.8) - faraday (>= 0.17.5, < 3.a) - jwt (>= 1.5, < 3.0) - multi_json (~> 1.10) - sinatra (2.2.2) - mustermann (~> 2.0) - rack (~> 2.2) - rack-protection (= 2.2.2) - tilt (~> 2.0) - spicy-proton (2.1.14) - bindata (~> 2.3) - statsd-ruby (1.5.0) - thrift (0.16.0) - tilt (2.0.11) - trailblazer-option (0.1.2) - uber (0.1.0) - webrick (1.7.0) - zonefile (1.06) - -PLATFORMS - universal-java-1.8 - -DEPENDENCIES - vmpooler! - vmpooler-provider-ec2! - vmpooler-provider-gce! - vmpooler-provider-vsphere! - -BUNDLED WITH - 2.3.18 diff --git a/docker/test-all-providers/docker-compose.yml b/docker/test-all-providers/docker-compose.yml deleted file mode 100644 index d93a8bb..0000000 --- a/docker/test-all-providers/docker-compose.yml +++ /dev/null @@ -1,71 +0,0 @@ -# For local development run with a dummy provider -version: '3.8' -services: - vmpooler-api: - build: - context: ./ - dockerfile: Dockerfile - volumes: - - type: bind - source: ${PWD}/vmpooler.yaml - target: /etc/vmpooler/vmpooler.yaml - ports: - - "8080:4567" - networks: - - redis-net - environment: - - VMPOOLER_DEBUG=true # for use of dummy auth - - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml - - REDIS_SERVER=redislocal - - LOGFILE=/dev/null - - VMPOOLER_TRACING_ENABLED=true - - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces - image: vmpooler-local - command: api - depends_on: - - redislocal - vmpooler-manager: - build: - context: ./ - dockerfile: Dockerfile - volumes: - - type: bind - source: ${PWD}/vmpooler.yaml - target: /etc/vmpooler/vmpooler.yaml - ports: - - "8081:4567" - networks: - - redis-net - environment: - - VMPOOLER_DEBUG=true # for use of dummy auth - - VMPOOLER_CONFIG_FILE=/etc/vmpooler/vmpooler.yaml - - REDIS_SERVER=redislocal - - LOGFILE=/dev/null - - VMPOOLER_TRACING_ENABLED=true - - VMPOOLER_TRACING_JAEGER_HOST=http://jaeger-aio:14268/api/traces - image: vmpooler-local - command: manager - depends_on: - - redislocal - redislocal: - image: redis - # Uncomment this if you don't want the redis data to persist - #command: "redis-server --save '' --appendonly no" - ports: - - "6379:6379" - networks: - - redis-net - jaeger-aio: - image: jaegertracing/all-in-one:1.18 - ports: - - "14250:14250" - - "8082:16686" - networks: - - redis-net - user: '1001' - read_only: true - cap_drop: - - ALL - -networks: - redis-net: diff --git a/docker/test-all-providers/docker-entrypoint.sh b/docker/test-all-providers/docker-entrypoint.sh deleted file mode 100644 index 07d11de..0000000 --- a/docker/test-all-providers/docker-entrypoint.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -e - -set -- bundle exec vmpooler "$@" - -exec "$@" diff --git a/docker/test-all-providers/update-gemfile-lock.sh b/docker/update-gemfile-lock similarity index 100% rename from docker/test-all-providers/update-gemfile-lock.sh rename to docker/update-gemfile-lock diff --git a/update-changelog b/update-changelog new file mode 100755 index 0000000..3cfe85a --- /dev/null +++ b/update-changelog @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +docker run -it --rm -e CHANGELOG_GITHUB_TOKEN -v $(pwd):/usr/local/src/your-app \ + githubchangeloggenerator/github-changelog-generator:1.16.2 \ + github_changelog_generator --future-release $(yq .version helm-charts/vmpooler/Chart.yaml) \ No newline at end of file diff --git a/update-chart-lock b/update-chart-lock new file mode 100755 index 0000000..8748596 --- /dev/null +++ b/update-chart-lock @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +docker run --rm -it -v $(pwd):/apps --entrypoint /bin/sh alpine/helm \ + -c 'helm repo add bitnami https://charts.bitnami.com/bitnami && cd /apps/helm-charts/vmpooler && helm dependency update' From 08d2180307bc1a4260000dd24be2d217a5603e7d Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Fri, 27 Jan 2023 11:54:51 -0500 Subject: [PATCH 3/6] Add changelog --- .github_changelog_generator | 3 + CHANGELOG.md | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 .github_changelog_generator create mode 100644 CHANGELOG.md diff --git a/.github_changelog_generator b/.github_changelog_generator new file mode 100644 index 0000000..560bbb9 --- /dev/null +++ b/.github_changelog_generator @@ -0,0 +1,3 @@ +project=vmpooler-deployment +user=puppetlabs +exclude_labels=maintenance \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..18d2b9a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,140 @@ +# Changelog + +## [1.19.0](https://github.com/puppetlabs/vmpooler-deployment/tree/1.19.0) (2022-08-26) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/3.0.0-prod-all-providers...1.19.0) + +**Merged pull requests:** + +- \(RE-14811\) Remove DIO as codeowners [\#60](https://github.com/puppetlabs/vmpooler-deployment/pull/60) ([yachub](https://github.com/yachub)) +- Add release-engineering to codeowners [\#55](https://github.com/puppetlabs/vmpooler-deployment/pull/55) ([yachub](https://github.com/yachub)) + +## [3.0.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/3.0.0-prod-all-providers) (2022-08-02) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.8.0-prod-all-providers...3.0.0-prod-all-providers) + +**Merged pull requests:** + +- \(maint\) Add the ec2 provider to our prod-all-providers Gemfile [\#54](https://github.com/puppetlabs/vmpooler-deployment/pull/54) ([sbeaulie](https://github.com/sbeaulie)) + +## [1.8.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.8.0-prod-all-providers) (2022-07-26) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.7.0-prod-all-providers...1.8.0-prod-all-providers) + +**Merged pull requests:** + +- \(maint\) Fix jruby startup [\#52](https://github.com/puppetlabs/vmpooler-deployment/pull/52) ([sbeaulie](https://github.com/sbeaulie)) +- \(maint\) Remove invokedymanicyield=false that was a workaround for jru… [\#51](https://github.com/puppetlabs/vmpooler-deployment/pull/51) ([sbeaulie](https://github.com/sbeaulie)) +- \(maint\) missing the archive [\#50](https://github.com/puppetlabs/vmpooler-deployment/pull/50) ([sbeaulie](https://github.com/sbeaulie)) + +## [1.7.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.7.0-prod-all-providers) (2022-07-25) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.6.0-prod-all-providers...1.7.0-prod-all-providers) + +**Merged pull requests:** + +- \(maint\) Upgrade to latest vmpooler with jruby 9.3.6 [\#49](https://github.com/puppetlabs/vmpooler-deployment/pull/49) ([sbeaulie](https://github.com/sbeaulie)) +- \(DIO-3229\) Add non sensitive parameters as ENV vars, and expect the s… [\#48](https://github.com/puppetlabs/vmpooler-deployment/pull/48) ([sbeaulie](https://github.com/sbeaulie)) +- Add a new values parameter overrideCmd [\#47](https://github.com/puppetlabs/vmpooler-deployment/pull/47) ([sbeaulie](https://github.com/sbeaulie)) + +## [1.6.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.6.0-prod-all-providers) (2022-06-21) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.5.0-prod-all-providers...1.6.0-prod-all-providers) + +**Implemented enhancements:** + +- \(DIO-3162\) Add support for disk\_type in gce [\#43](https://github.com/puppetlabs/vmpooler-deployment/pull/43) ([sbeaulie](https://github.com/sbeaulie)) + +**Merged pull requests:** + +- \(DIO-3157\) Update ingress for k8s 1.22 [\#42](https://github.com/puppetlabs/vmpooler-deployment/pull/42) ([suckatrash](https://github.com/suckatrash)) +- Update release-helm-charts.yml [\#41](https://github.com/puppetlabs/vmpooler-deployment/pull/41) ([sbeaulie](https://github.com/sbeaulie)) +- Update release-helm-charts.yml [\#40](https://github.com/puppetlabs/vmpooler-deployment/pull/40) ([sbeaulie](https://github.com/sbeaulie)) +- \(DIO-2812\) Add CI for charts [\#21](https://github.com/puppetlabs/vmpooler-deployment/pull/21) ([genebean](https://github.com/genebean)) + +## [1.5.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.5.0-prod-all-providers) (2022-04-19) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.4.0-prod-all-providers...1.5.0-prod-all-providers) + +**Implemented enhancements:** + +- Bump vmpooler-provider-gce gem to include hostname fix [\#37](https://github.com/puppetlabs/vmpooler-deployment/pull/37) ([yachub](https://github.com/yachub)) + +**Merged pull requests:** + +- Deploy v1.11.1 [\#36](https://github.com/puppetlabs/vmpooler-deployment/pull/36) ([sbeaulie](https://github.com/sbeaulie)) + +## [1.4.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.4.0-prod-all-providers) (2022-04-07) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.3.0-prod-all-providers...1.4.0-prod-all-providers) + +**Merged pull requests:** + +- \(DIO-2833\) Bump the gemfile too since this is used for building the i… [\#35](https://github.com/puppetlabs/vmpooler-deployment/pull/35) ([sbeaulie](https://github.com/sbeaulie)) +- \(DIO-2833\) Chart version using the latest code from vmpooler to suppo… [\#34](https://github.com/puppetlabs/vmpooler-deployment/pull/34) ([sbeaulie](https://github.com/sbeaulie)) + +## [1.3.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.3.0-prod-all-providers) (2022-03-30) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.2.0-prod-all-providers...1.3.0-prod-all-providers) + +**Merged pull requests:** + +- fix annotations [\#33](https://github.com/puppetlabs/vmpooler-deployment/pull/33) ([sbeaulie](https://github.com/sbeaulie)) +- \(maint\) set extra\_config the same way we do the manager app [\#32](https://github.com/puppetlabs/vmpooler-deployment/pull/32) ([sbeaulie](https://github.com/sbeaulie)) +- deploy chart v1.9.0 [\#31](https://github.com/puppetlabs/vmpooler-deployment/pull/31) ([sbeaulie](https://github.com/sbeaulie)) +- \(maint\) Update redis version, add env REDIS\_RECONNECT\_ATTEMPTS [\#30](https://github.com/puppetlabs/vmpooler-deployment/pull/30) ([sbeaulie](https://github.com/sbeaulie)) +- Including vmpooler-provider-gce in the Gemfile [\#22](https://github.com/puppetlabs/vmpooler-deployment/pull/22) ([sbeaulie](https://github.com/sbeaulie)) + +## [1.2.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.2.0-prod-all-providers) (2021-12-13) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.1.0-prod-all-providers...1.2.0-prod-all-providers) + +**Merged pull requests:** + +- Update vmpooler chart to accept image tag override [\#20](https://github.com/puppetlabs/vmpooler-deployment/pull/20) ([genebean](https://github.com/genebean)) + +## [1.1.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.1.0-prod-all-providers) (2021-12-13) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/1.0.0-prod-all-providers...1.1.0-prod-all-providers) + +**Merged pull requests:** + +- Update gemfiles post vsphere provider 1.5 release [\#19](https://github.com/puppetlabs/vmpooler-deployment/pull/19) ([genebean](https://github.com/genebean)) + +## [1.0.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/1.0.0-prod-all-providers) (2021-12-09) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/0.1.1-prod-all-providers...1.0.0-prod-all-providers) + +**Merged pull requests:** + +- General updates related to packaging [\#18](https://github.com/puppetlabs/vmpooler-deployment/pull/18) ([genebean](https://github.com/genebean)) + +## [0.1.1-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/0.1.1-prod-all-providers) (2021-12-09) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/0.1.0-prod-all-providers...0.1.1-prod-all-providers) + +**Merged pull requests:** + +- Update build workflow output [\#17](https://github.com/puppetlabs/vmpooler-deployment/pull/17) ([genebean](https://github.com/genebean)) + +## [0.1.0-prod-all-providers](https://github.com/puppetlabs/vmpooler-deployment/tree/0.1.0-prod-all-providers) (2021-12-09) + +[Full Changelog](https://github.com/puppetlabs/vmpooler-deployment/compare/074778d0b021afefdffed1931228954f9adbd9f6...0.1.0-prod-all-providers) + +**Merged pull requests:** + +- Add dockerfile param to CI workflow [\#16](https://github.com/puppetlabs/vmpooler-deployment/pull/16) ([genebean](https://github.com/genebean)) +- Add prod container setup [\#15](https://github.com/puppetlabs/vmpooler-deployment/pull/15) ([genebean](https://github.com/genebean)) +- Add prod container setup [\#13](https://github.com/puppetlabs/vmpooler-deployment/pull/13) ([genebean](https://github.com/genebean)) +- Bump vmpooler from `5f89131` to `3c61050` in /docker/test-all-providers [\#12](https://github.com/puppetlabs/vmpooler-deployment/pull/12) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Update docker setup for testing [\#11](https://github.com/puppetlabs/vmpooler-deployment/pull/11) ([genebean](https://github.com/genebean)) +- Revert api's extra\_config param [\#10](https://github.com/puppetlabs/vmpooler-deployment/pull/10) ([genebean](https://github.com/genebean)) +- Fix templating in api deployment [\#9](https://github.com/puppetlabs/vmpooler-deployment/pull/9) ([genebean](https://github.com/genebean)) +- Bump default timoutes for redis health checks [\#8](https://github.com/puppetlabs/vmpooler-deployment/pull/8) ([genebean](https://github.com/genebean)) +- Add more details to Helm repo section [\#5](https://github.com/puppetlabs/vmpooler-deployment/pull/5) ([genebean](https://github.com/genebean)) +- Create Helm repository [\#4](https://github.com/puppetlabs/vmpooler-deployment/pull/4) ([genebean](https://github.com/genebean)) +- Add icon to Helm chart [\#3](https://github.com/puppetlabs/vmpooler-deployment/pull/3) ([genebean](https://github.com/genebean)) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* From 6573bb6dd75149ecd361e3e6f76d0b7a93ab6595 Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Mon, 23 Jan 2023 17:49:50 -0500 Subject: [PATCH 4/6] Add build on pull request --- .github/workflows/build.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..a28109c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,37 @@ +name: Docker Build + +on: pull_request + +permissions: + contents: read + packages: write + +jobs: + build: + name: Docker Build and Push + if: contains(github.event.pull_request.labels.*.name, 'documentation') != true + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.ref }} + clean: true + fetch-depth: 0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: docker + push: true + tags: ghcr.io/${{ github.repository }}/vmpooler:pr${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} From f1563ed601c58e3996a5bfbe47d239942abcf3be Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Tue, 24 Jan 2023 07:42:03 -0500 Subject: [PATCH 5/6] Bump redis chart as the current version doesn't exist --- helm-charts/vmpooler/Chart.lock | 6 +++--- helm-charts/vmpooler/Chart.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helm-charts/vmpooler/Chart.lock b/helm-charts/vmpooler/Chart.lock index 03de6e8..d5fddf2 100644 --- a/helm-charts/vmpooler/Chart.lock +++ b/helm-charts/vmpooler/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: redis repository: https://charts.bitnami.com/bitnami - version: 16.10.1 -digest: sha256:b4278d10dd3a151323b761106d2ab00a742b08984d05e9102f852815d69d1a6a -generated: "2022-06-03T11:04:59.151842094-07:00" + version: 16.13.2 +digest: sha256:3a3d3cfce254ddfa488e495a3e2e141ee59c0ea4a583ba813093def78ca132cb +generated: "2023-01-24T12:41:13.082268468Z" diff --git a/helm-charts/vmpooler/Chart.yaml b/helm-charts/vmpooler/Chart.yaml index 6a08495..08575fd 100644 --- a/helm-charts/vmpooler/Chart.yaml +++ b/helm-charts/vmpooler/Chart.yaml @@ -8,4 +8,4 @@ appVersion: 1.8.0-prod-all-providers dependencies: - name: redis repository: https://charts.bitnami.com/bitnami - version: 16.10.1 + version: 16.13.2 From 91c3c989045dc9d856e7777fc165ba77ec29e6ed Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Fri, 27 Jan 2023 11:40:43 -0500 Subject: [PATCH 6/6] Add test and release workflow --- .../container-all-prod-providers.yml | 47 ----- .github/workflows/release-helm-charts.yml | 68 -------- .github/workflows/release.yml | 161 ++++++++++++++++++ .github/workflows/test.yml | 28 +++ 4 files changed, 189 insertions(+), 115 deletions(-) delete mode 100644 .github/workflows/container-all-prod-providers.yml delete mode 100644 .github/workflows/release-helm-charts.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/container-all-prod-providers.yml b/.github/workflows/container-all-prod-providers.yml deleted file mode 100644 index b9e1032..0000000 --- a/.github/workflows/container-all-prod-providers.yml +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: Container with all prod providers -on: - workflow_dispatch: - inputs: - tag: - description: 'Tag in semver format' - required: true - -jobs: - container_prod_all_providers: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 # Checking out the repo - - name: Build and Publish Docker image - uses: VaultVulp/gp-docker-action@1.2.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - image-name: vmpooler - build-context: ./docker/prod-all-providers/ - dockerfile: ./docker/prod-all-providers/Dockerfile - image-tag: ${{ github.event.inputs.tag }}-prod-all-providers - - name: Generate Release Body - env: - RELEASE_BODY_FILE: "${{ github.event.inputs.tag }}-prod-all-providers-release-body.md" - run: | - echo "## Components" > ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "This release includes the following:" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "### Source image" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "- $(grep ^FROM ./docker/prod-all-providers/Dockerfile |cut -d ' ' -f2) + OS updates" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "### Gems" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "$(grep -e 'vmpooler ([0-9]' docker/prod-all-providers/Gemfile.lock | xargs -L1 echo -)" >> ${RELEASE_BODY_FILE} - echo "$(grep -e 'vmpooler-provider-.* ([0-9]' docker/prod-all-providers/Gemfile.lock | xargs -L1 echo -)" >> ${RELEASE_BODY_FILE} - - name: Tag Release - uses: ncipollo/release-action@v1 - with: - tag: ${{ github.event.inputs.tag }}-prod-all-providers - token: ${{ secrets.GITHUB_TOKEN }} - draft: false - prerelease: false - bodyFile: ${{ github.event.inputs.tag }}-prod-all-providers-release-body.md - generateReleaseNotes: true \ No newline at end of file diff --git a/.github/workflows/release-helm-charts.yml b/.github/workflows/release-helm-charts.yml deleted file mode 100644 index e909cc6..0000000 --- a/.github/workflows/release-helm-charts.yml +++ /dev/null @@ -1,68 +0,0 @@ ---- -name: Release Helm charts -on: - workflow_dispatch: - inputs: - tag: - description: 'Tag in semver format' - required: true - type: string - -jobs: - container_prod_all_providers: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # ct list-changed below needs this - - uses: azure/setup-helm@v1 - - uses: actions/setup-python@v2 - with: - python-version: 3.7 - - name: Set up chart-testing - uses: helm/chart-testing-action@v2.1.0 - - name: Run chart-testing (list-changed) - id: list-changed - run: | - changed=$(ct list-changed --chart-dirs helm-charts --target-branch main) - if [[ -n "$changed" ]]; then - echo "::set-output name=changed::true" - fi - - name: Run chart-testing (lint) - run: ct lint --chart-dirs helm-charts --all --validate-maintainers=false --chart-repos bitnami=https://charts.bitnami.com/bitnami - - name: Package charts - run: | - set -e - cd docs/ - helm package ../helm-charts/* - helm repo index --url https://puppetlabs.github.io/vmpooler-deployment/ . - - uses: EndBug/add-and-commit@v9 # You can change this to use a specific version. - with: - add: docs - message: release helm-chart version ${{ github.event.inputs.tag }} - - name: Generate Release Body - env: - RELEASE_BODY_FILE: "${{ github.event.inputs.tag }}-prod-all-providers-release-body.md" - run: | - echo "#Components" > ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "This release includes the following:" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "##Source image" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "- $(grep ^FROM ./docker/prod-all-providers/Dockerfile |cut -d ' ' -f2) + OS updates" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "##Gems" >> ${RELEASE_BODY_FILE} - echo "" >> ${RELEASE_BODY_FILE} - echo "$(grep -e 'vmpooler ([0-9]' docker/prod-all-providers/Gemfile.lock | xargs -L1 echo -)" >> ${RELEASE_BODY_FILE} - echo "$(grep -e 'vmpooler-provider-.* ([0-9]' docker/prod-all-providers/Gemfile.lock | xargs -L1 echo -)" >> ${RELEASE_BODY_FILE} - echo "${RELEASE_BODY_FILE}" - - name: Tag Release - uses: ncipollo/release-action@v1 - with: - tag: ${{ github.event.inputs.tag }}-prod-all-providers - token: ${{ secrets.GITHUB_TOKEN }} - draft: false - prerelease: false - bodyFile: ${{ github.event.inputs.tag }}-prod-all-providers-release-body.md - generateReleaseNotes: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..cf4d035 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,161 @@ +name: Docker and Helm Release + +on: + workflow_dispatch: + +permissions: + contents: write + issues: read + pull-requests: read + packages: write + +jobs: + release: + name: Validate Docs, Tag, and Docker Push & Helm Push + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.BOT_TOKEN }} + + - name: Get New Chart Version + id: nv + run: | + version=$(yq .version helm-charts/vmpooler/Chart.yaml) + appVersion=$(yq .appVersion helm-charts/vmpooler/Chart.yaml) + echo "version=$version" >> $GITHUB_OUTPUT + echo "appVersion=$appVersion" >> $GITHUB_OUTPUT + echo "Found version $version from helm-charts/vmpooler/Chart.yaml" + echo "Found appVersion $appVersion from helm-charts/vmpooler/Chart.yaml" + + - name: Get Current Chart Version + uses: actions/github-script@v6 + id: cv + with: + script: | + const { data: response } = await github.rest.repos.getLatestRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + }) + console.log(`The latest release is ${response.tag_name}`) + return response.tag_name + result-encoding: string + + - name: Get Current Docker Tag + uses: actions/github-script@v6 + id: dv + with: + script: | + // concat to build "vmpooler-deployment%2Fvmpooler" + const packageName = [context.repo.repo, 'vmpooler'].join('/'); + + const shouldRunDockerBuild = async () => { + let runDockerBuild = true; + // Iterate through all pages of list of package versions + for await (const response of github.paginate.iterator( + github.rest.packages.getAllPackageVersionsForPackageOwnedByOrg, + { + package_type: 'container', + package_name: packageName, + org: context.repo.owner, + } + )) { + // Loop through each version, destructure down to the tags array and search for existing tag + for (const data of response.data) { + const { metadata: { container: { tags }}} = data; + console.log('List of docker tags:', tags); + if (tags.includes("${{ steps.nv.outputs.appVersion }}")) { + // Existing tag found, return false so that docker build does not run + console.log('Found existing tag for', "${{ steps.nv.outputs.appVersion }}"); + runDockerBuild = false; + break; + }; + }; + }; + return runDockerBuild; + }; + + const returnValue = await shouldRunDockerBuild(); + console.log('return:', returnValue); + return returnValue; + + - name: Generate Changelog + uses: docker://githubchangeloggenerator/github-changelog-generator:1.16.2 + with: + args: >- + --future-release ${{ steps.nv.outputs.version }} + env: + CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Validate Changelog + run : | + set -e + if [[ -n $(git status --porcelain) ]]; then + echo "Here is the current git status:" + git status + echo + echo "The following changes were detected:" + git --no-pager diff + echo "Uncommitted PRs found in the changelog. Please submit a release prep PR of changes after running 'docker run -it --rm -e CHANGELOG_GITHUB_TOKEN -v "\$\(pwd\)":/usr/local/src/your-app githubchangeloggenerator/github-changelog-generator:1.16.2 github_changelog_generator --future-release ${{ steps.nv.outputs.version }}'" + exit 1 + fi + + - name: Generate Release Notes + uses: docker://githubchangeloggenerator/github-changelog-generator:1.16.2 + with: + args: >- + --since-tag ${{ steps.cv.outputs.result }} + --future-release ${{ steps.nv.outputs.version }} + --output release-notes.md + env: + CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Tag Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.nv.outputs.version }} + token: ${{ secrets.GITHUB_TOKEN }} + bodyfile: release-notes.md + draft: false + prerelease: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker + if: ${{ steps.dv.outputs.result == 'true' }} + uses: docker/build-push-action@v3 + with: + push: true + tags: | + ghcr.io/${{ github.repository }}:${{ steps.nv.outputs.appVersion }} + ghcr.io/${{ github.repository }}:latest + + - uses: azure/setup-helm@v3 + + - uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Package Helm charts + run: | + set -e + cd docs/ + helm package ../helm-charts/* + helm repo index --url https://puppetlabs.github.io/vmpooler-deployment/ . + + - name: Git Commit and Push Helm Charts + run: | + git config user.name "puppetlabs-jenkins" + git config user.email "team-quality-engineering@puppet.com" + git --no-pager diff CHANGELOG.md + git add CHANGELOG.md + git commit -m "release helm-chart version ${{ steps.nv.outputs.version }}" + git push diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..374e8f8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,28 @@ +name: Helm Test + +on: pull_request + +jobs: + test: + name: Test Helm Chart + if: contains(github.event.pull_request.labels.*.name, 'documentation') != true + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.ref }} + clean: true + fetch-depth: 0 + + - uses: azure/setup-helm@v3 + + - uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Run chart-testing (lint) + run: ct lint --chart-dirs helm-charts --all --validate-maintainers=false --chart-repos bitnami=https://charts.bitnami.com/bitnami