├── .gitignore ├── .github ├── banner.png ├── workflows │ ├── release.yml │ ├── branch.yml │ ├── test-helm-raw-default-kube-version.yml │ ├── test-destroy.yml │ ├── test-helmfile-raw-default-kube-version.yml │ ├── test-helm-raw.yml │ └── test-helmfile-raw.yml ├── settings.yml └── disabled │ └── test-helm-raw-additional-args.yml ├── atmos.yaml ├── renovate.json ├── src └── argocd-application │ ├── values.yaml │ ├── .helmignore │ ├── templates │ ├── application.yaml │ └── _helpers.tpl │ └── Chart.yaml ├── test ├── helm │ └── example-app │ │ ├── templates │ │ ├── configmap.yaml │ │ ├── serviceaccount.yaml │ │ ├── service.yaml │ │ ├── tests │ │ │ └── test-connection.yaml │ │ ├── hpa.yaml │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── deployment.yaml │ │ └── ingress.yaml │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ └── values.yaml └── helmfile │ └── helmfile.yaml ├── README.yaml ├── LICENSE ├── README.md └── action.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .build-harness 2 | build-harness -------------------------------------------------------------------------------- /.github/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudposse/github-action-deploy-argocd/HEAD/.github/banner.png -------------------------------------------------------------------------------- /atmos.yaml: -------------------------------------------------------------------------------- 1 | import: 2 | - https://raw.githubusercontent.com/cloudposse/.github/refs/heads/main/.github/atmos/github-action.yaml 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/argocd-application/values.yaml: -------------------------------------------------------------------------------- 1 | project: default 2 | targetNamespace: 3 | createNamespace: false 4 | path: 5 | repository: 6 | sha: 7 | values: 8 | image: 9 | repository: nginx 10 | tag: "" 11 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: test 5 | data: 6 | {{ with .Values.foo -}} 7 | foo: '{{ . }}' 8 | {{- end }} 9 | {{ with .Values.bar -}} 10 | bar: '{{ . }}' 11 | {{- end }} -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | release: 4 | types: [published] 5 | 6 | permissions: 7 | id-token: write 8 | contents: write 9 | pull-requests: write 10 | 11 | jobs: 12 | github-action: 13 | uses: cloudposse/.github/.github/workflows/shared-release-branches.yml@main 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # Upstream changes from _extends are only recognized when modifications are made to this file in the default branch. 2 | _extends: .github 3 | repository: 4 | name: github-action-deploy-argocd 5 | description: Deploy on Kubernetes with Helm/Helmfile and ArgoCD 6 | homepage: https://cloudposse.com/accelerate 7 | topics: "" 8 | 9 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "example-app.serviceAccountName" . }} 6 | labels: 7 | {{- include "example-app.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "example-app.fullname" . }} 5 | labels: 6 | {{- include "example-app.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "example-app.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /test/helm/example-app/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /src/argocd-application/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "example-app.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "example-app.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "example-app.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /.github/workflows/branch.yml: -------------------------------------------------------------------------------- 1 | name: Branch 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | - release/** 7 | types: [opened, synchronize, reopened] 8 | push: 9 | branches: 10 | - main 11 | - release/v* 12 | paths-ignore: 13 | - '.github/**' 14 | - 'docs/**' 15 | - 'examples/**' 16 | - 'test/**' 17 | - 'README.md' 18 | 19 | permissions: 20 | contents: write 21 | actions: write 22 | 23 | jobs: 24 | github-action: 25 | uses: cloudposse/.github/.github/workflows/shared-github-action.yml@main 26 | secrets: inherit 27 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "example-app.fullname" . }} 6 | labels: 7 | {{- include "example-app.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "example-app.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /src/argocd-application/templates/application.yaml: -------------------------------------------------------------------------------- 1 | {{ $root := .}} 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: {{ .Release.Name | quote }} 6 | labels: 7 | {{- include "argocd-application.labels" . | nindent 4 }} 8 | finalizers: 9 | - resources-finalizer.argocd.argoproj.io 10 | spec: 11 | destination: 12 | namespace: {{ .Values.targetNamespace | quote }} 13 | server: 'https://kubernetes.default.svc' 14 | project: {{ .Values.project | quote }} 15 | source: 16 | path: {{ .Values.path | quote }} 17 | repoURL: {{ .Values.repository | quote }} 18 | targetRevision: {{ .Values.sha | quote }} 19 | helm: 20 | version: v3 21 | values: | 22 | {{- toYaml .Values.values | nindent 8 }} 23 | parameters: 24 | - name: image.repository 25 | value: {{ .Values.image.repository | quote }} 26 | - name: image.tag 27 | value: {{ .Values.image.tag | quote }} 28 | syncPolicy: 29 | automated: 30 | prune: true 31 | selfHeal: true 32 | syncOptions: 33 | - CreateNamespace={{ .Values.createNamespace }} 34 | -------------------------------------------------------------------------------- /src/argocd-application/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: argocd-application 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | appVersion: 1.16.0 24 | -------------------------------------------------------------------------------- /test/helm/example-app/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: example-app 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "example-app.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "example-app.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "example-app.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "example-app.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "example-app.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "example-app.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "example-app.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "example-app.labels" -}} 37 | helm.sh/chart: {{ include "example-app.chart" . }} 38 | {{ include "example-app.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "example-app.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "example-app.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "example-app.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "example-app.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "example-app.fullname" . }} 5 | labels: 6 | {{- include "example-app.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "example-app.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "example-app.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "example-app.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: {{ .Values.service.port }} 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /src/argocd-application/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "argocd-application.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "argocd-application.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "argocd-application.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "argocd-application.labels" -}} 37 | helm.sh/chart: {{ include "argocd-application.chart" . }} 38 | {{ include "argocd-application.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "argocd-application.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "argocd-application.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "argocd-application.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "argocd-application.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /test/helm/example-app/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for example-app. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | imagePullSecrets: [] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: ClusterIP 41 | port: 80 42 | 43 | ingress: 44 | enabled: true 45 | className: "" 46 | annotations: {} 47 | # kubernetes.io/ingress.class: nginx 48 | # kubernetes.io/tls-acme: "true" 49 | hosts: 50 | - host: chart-example.local 51 | paths: 52 | - path: / 53 | pathType: ImplementationSpecific 54 | tls: [] 55 | # - secretName: chart-example-tls 56 | # hosts: 57 | # - chart-example.local 58 | 59 | resources: {} 60 | # We usually recommend not to specify default resources and to leave this as a conscious 61 | # choice for the user. This also increases chances charts run on environments with little 62 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 63 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 64 | # limits: 65 | # cpu: 100m 66 | # memory: 128Mi 67 | # requests: 68 | # cpu: 100m 69 | # memory: 128Mi 70 | 71 | autoscaling: 72 | enabled: false 73 | minReplicas: 1 74 | maxReplicas: 100 75 | targetCPUUtilizationPercentage: 80 76 | # targetMemoryUtilizationPercentage: 80 77 | 78 | nodeSelector: {} 79 | 80 | tolerations: [] 81 | 82 | affinity: {} 83 | 84 | platform: 85 | -------------------------------------------------------------------------------- /test/helmfile/helmfile.yaml: -------------------------------------------------------------------------------- 1 | environments: 2 | default: 3 | preview: 4 | staging: 5 | production: 6 | 7 | 8 | repositories: 9 | # Cloud Posse incubator repo of helm charts 10 | - name: "cloudposse-incubator" 11 | url: "https://charts.cloudposse.com/incubator/" 12 | 13 | 14 | 15 | releases: 16 | # 17 | # References: 18 | # - https://github.com/cloudposse/charts/blob/master/incubator/monochart 19 | # 20 | - name: 'example-app' 21 | labels: 22 | preview: "true" 23 | chart: "cloudposse-incubator/monochart" 24 | version: "0.26.0" 25 | wait: true 26 | force: true 27 | recreatePods: false 28 | values: 29 | - image: 30 | repository: '{{ env "IMAGE_NAME" | default "cloudposse/example-app" }}' 31 | tag: '{{ env "IMAGE_TAG" | default "0.1.0" }}' 32 | pullPolicy: Always 33 | replicaCount: 2 34 | # Deployment configuration 35 | deployment: 36 | enabled: true 37 | strategy: 38 | type: "RollingUpdate" 39 | rollingUpdate: 40 | maxUnavailable: 1 41 | revisionHistoryLimit: 10 42 | 43 | # Configuration Settings 44 | configMaps: 45 | default: 46 | enabled: true 47 | 48 | # Service endpoint 49 | service: 50 | enabled: true 51 | type: ClusterIP 52 | ports: 53 | default: 54 | internal: 8080 55 | external: 80 56 | 57 | ingress: 58 | default: 59 | enabled: true 60 | port: default 61 | annotations: 62 | external-dns.alpha.kubernetes.io/target: {{ .StateValues.platform.default_ingress_domain }} 63 | alb.ingress.kubernetes.io/group.name: {{ .StateValues.platform.default_alb_ingress_group }} 64 | kubernetes.io/ingress.class: alb 65 | alb.ingress.kubernetes.io/scheme: internet-facing 66 | alb.ingress.kubernetes.io/actions.ssl-redirect: '{"RedirectConfig":{"Port":"443","Protocol":"HTTPS","StatusCode":"HTTP_301"},"Type":"redirect"}' 67 | alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' 68 | alb.ingress.kubernetes.io/ssl-redirect: "443" 69 | alb.ingress.kubernetes.io/target-type: ip 70 | {{- if eq .Environment.Name "preview" }} 71 | external-dns.alpha.kubernetes.io/hostname: example-app-pr-{{ .Namespace }}.{{ .StateValues.platform.default_ingress_domain }} 72 | outputs.platform.cloudposse.com/webapp-url: "https://example-app-pr-{{ .Namespace }}.{{ .Values.platform.default_ingress_domain }}/dashboard" 73 | hosts: 74 | "example-app-pr-{{ .Namespace }}.{{ .StateValues.platform.default_ingress_domain }}": /* 75 | {{- else }} 76 | external-dns.alpha.kubernetes.io/hostname: example-app.{{ .StateValues.platform.default_ingress_domain }} 77 | outputs.platform.cloudposse.com/webapp-url: "https://example-app.{{ .Values.platform.default_ingress_domain }}/dashboard" 78 | hosts: 79 | "example-app.{{ .StateValues.platform.default_ingress_domain }}": /* 80 | {{- end }} 81 | 82 | probes: 83 | # Probe that ensures service is healthy 84 | livenessProbe: 85 | httpGet: 86 | path: /healthz 87 | port: default 88 | scheme: HTTP 89 | periodSeconds: 3 90 | initialDelaySeconds: 3 91 | timeoutSeconds: 3 92 | successThreshold: 1 93 | failureThreshold: 2 94 | 95 | # Probe that ensures service has started 96 | readinessProbe: 97 | httpGet: 98 | path: /healthz 99 | port: default 100 | scheme: HTTP 101 | periodSeconds: 3 102 | initialDelaySeconds: 3 103 | timeoutSeconds: 3 104 | successThreshold: 1 105 | failureThreshold: 2 106 | 107 | resources: 108 | requests: 109 | memory: 10Mi 110 | cpu: 100m 111 | limits: 112 | memory: 10Mi 113 | cpu: 100m 114 | -------------------------------------------------------------------------------- /test/helm/example-app/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "example-app.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "example-app.labels" . | nindent 4 }} 21 | annotations: 22 | {{- with .Values.ingress.annotations }} 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | {{- if eq .Values.environment "preview" }} 26 | external-dns.alpha.kubernetes.io/hostname: example-app-pr-{{ .Namespace }}.{{ .Values.platform.default_ingress_domain }} 27 | outputs.platform.cloudposse.com/webapp-url: "https://example-app-pr-{{ .Namespace }}.{{ .Values.platform.default_ingress_domain }}/dashboard" 28 | {{- else }} 29 | external-dns.alpha.kubernetes.io/hostname: example-app.{{ .Values.platform.default_ingress_domain }} 30 | outputs.platform.cloudposse.com/webapp-url: "https://example-app.{{ .Values.platform.default_ingress_domain }}/dashboard" 31 | {{- end }} 32 | kubernetes.io/ingress.class: alb 33 | alb.ingress.kubernetes.io/scheme: internet-facing 34 | alb.ingress.kubernetes.io/actions.ssl-redirect: '{"RedirectConfig":{"Port":"443","Protocol":"HTTPS","StatusCode":"HTTP_301"},"Type":"redirect"}' 35 | alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' 36 | alb.ingress.kubernetes.io/ssl-redirect: "443" 37 | alb.ingress.kubernetes.io/target-type: ip 38 | spec: 39 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 40 | ingressClassName: {{ .Values.ingress.className }} 41 | {{- end }} 42 | {{- if .Values.ingress.tls }} 43 | tls: 44 | {{- range .Values.ingress.tls }} 45 | - hosts: 46 | hosts: 47 | {{- if eq .Values.environment "preview" }} 48 | - "example-app-pr-{{ .Namespace }}.{{ .Values.platform.default_ingress_domain }}" 49 | {{- else }} 50 | - "example-app.{{ .Values.platform.default_ingress_domain }}" 51 | {{- end }} 52 | {{- range .hosts }} 53 | - {{ . | quote }} 54 | {{- end }} 55 | secretName: {{ .secretName }} 56 | {{- end }} 57 | {{- end }} 58 | rules: 59 | - http: 60 | paths: 61 | - path: / 62 | backend: 63 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 64 | service: 65 | name: {{ $fullName }} 66 | port: 67 | number: {{ $svcPort }} 68 | {{- else }} 69 | serviceName: {{ $fullName }} 70 | servicePort: {{ $svcPort }} 71 | {{- end }} 72 | {{- if eq .Values.environment "preview" }} 73 | host: "example-app-pr-{{ .Namespace }}.{{ .Values.platform.default_ingress_domain }}" 74 | {{- else }} 75 | host: "example-app.{{ .Values.platform.default_ingress_domain }}" 76 | {{- end }} 77 | {{- range .Values.ingress.hosts }} 78 | - host: {{ .host | quote }} 79 | http: 80 | paths: 81 | {{- range .paths }} 82 | - path: {{ .path }} 83 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 84 | pathType: {{ .pathType }} 85 | {{- end }} 86 | backend: 87 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 88 | service: 89 | name: {{ $fullName }} 90 | port: 91 | number: {{ $svcPort }} 92 | {{- else }} 93 | serviceName: {{ $fullName }} 94 | servicePort: {{ $svcPort }} 95 | {{- end }} 96 | {{- end }} 97 | {{- end }} 98 | {{- end }} 99 | -------------------------------------------------------------------------------- /README.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # This is the canonical configuration for the `README.md` 3 | # Run `make readme` to rebuild the `README.md` 4 | # 5 | 6 | # Name of this project 7 | name: github-action-deploy-argocd 8 | 9 | # Tags of this project 10 | tags: 11 | - github-action 12 | 13 | # Logo for this project 14 | #logo: docs/logo.png 15 | 16 | # License of this project 17 | license: "APACHE2" 18 | 19 | # Canonical GitHub repo 20 | github_repo: cloudposse/github-action-deploy-argocd 21 | 22 | # Badges to display 23 | badges: 24 | - name: Latest Release 25 | image: https://img.shields.io/github/release/cloudposse/github-action-deploy-argocd.svg?style=for-the-badge 26 | url: https://github.com/cloudposse/github-action-deploy-argocd/releases/latest 27 | - name: Last Updated 28 | image: https://img.shields.io/github/last-commit/cloudposse/github-action-deploy-argocd.svg?style=for-the-badge 29 | url: https://github.com/cloudposse/github-action-deploy-argocd/commits 30 | - name: Slack Community 31 | image: https://slack.cloudposse.com/for-the-badge.svg 32 | url: https://cloudposse.com/slack 33 | 34 | # List any related terraform modules that this module may be used with or that this module depends on. 35 | related: [] 36 | 37 | # Short description of this project 38 | description: Deploy on Kubernetes with ArgoCD 39 | 40 | introduction: |- 41 | Deploy on Kubernetes with Helm/HelmFile and ArgoCD. 42 | 43 | references: 44 | - name: "github-actions-workflows" 45 | description: "Reusable workflows for different types of projects" 46 | url: "https://github.com/cloudposse/github-actions-workflows" 47 | 48 | 49 | # How to use this project 50 | usage: |- 51 | Deploy environment 52 | ```yaml 53 | name: Pull Request 54 | on: 55 | pull_request: 56 | branches: [ 'main' ] 57 | types: [opened, synchronize, reopened] 58 | 59 | jobs: 60 | deploy: 61 | runs-on: ubuntu-latest 62 | environment: 63 | name: preview 64 | url: ${{ steps.deploy.outputs.webapp-url }} 65 | steps: 66 | 67 | - name: Configure AWS Credentials 68 | uses: aws-actions/configure-aws-credentials@v1.7.0 69 | with: 70 | aws-region: us-west-2 71 | role-to-assume: arn:aws:iam::111111111111:role/preview 72 | role-session-name: deploy 73 | 74 | - name: Deploy 75 | uses: cloudposse/github-action-deploy-argocd@main 76 | id: deploy 77 | with: 78 | cluster: https://github.com/cloudposse/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 79 | toolchain: helmfile 80 | environment: preview 81 | namespace: preview 82 | application: test-app 83 | github-pat: ${{ secrets.GITHUB_AUTH_PAT }} 84 | repository: ${{ github.repository }} 85 | ref: ${{ github.event.pull_request.head.ref }} 86 | image: nginx 87 | image-tag: latest 88 | operation: deploy 89 | debug: false 90 | synchronously: true 91 | ``` 92 | 93 | 94 | Destroy environment 95 | ```yaml 96 | name: Pull Request 97 | on: 98 | pull_request: 99 | branches: [ 'main' ] 100 | types: [closed] 101 | 102 | jobs: 103 | destroy: 104 | runs-on: ubuntu-latest 105 | steps: 106 | - name: Configure AWS Credentials 107 | uses: aws-actions/configure-aws-credentials@v1.7.0 108 | with: 109 | aws-region: us-west-2 110 | role-to-assume: arn:aws:iam::111111111111:role/preview 111 | role-session-name: destroy 112 | 113 | - name: Destroy 114 | uses: cloudposse/github-action-deploy-helmfile@main 115 | id: destroy 116 | with: 117 | cluster: https://github.com/cloudposse/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 118 | toolchain: helmfile 119 | environment: preview 120 | namespace: preview 121 | application: test-app 122 | github-pat: ${{ secrets.GITHUB_AUTH_PAT }} 123 | repository: ${{ github.repository }} 124 | ref: ${{ github.event.pull_request.head.ref }} 125 | image: "" 126 | image-tag: "" 127 | operation: destroy 128 | debug: false 129 | ``` 130 | 131 | include: [] 132 | contributors: [] 133 | -------------------------------------------------------------------------------- /.github/workflows/test-helm-raw-default-kube-version.yml: -------------------------------------------------------------------------------- 1 | name: Test - Helm raw - default kubernetes version 2 | on: 3 | # # Uncomment when test added first time to register workflow and comment it back after workflow would be registered 4 | # # 5 | # # Added pull_request to register workflow from the PR. 6 | # # Read more https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo 7 | # pull_request: {} 8 | workflow_dispatch: 9 | inputs: 10 | ref: 11 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 12 | required: false 13 | type: string 14 | sha: 15 | description: "The sha of the commit that triggered the workflow run" 16 | required: false 17 | type: string 18 | 19 | jobs: 20 | setup: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Setup 24 | run: echo "Do setup" 25 | 26 | - id: random 27 | shell: bash 28 | run: |- 29 | echo "password=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 30 | 31 | outputs: 32 | random: ${{ steps.random.outputs.password }} 33 | 34 | test: 35 | runs-on: ubuntu-latest 36 | environment: terratest 37 | continue-on-error: true 38 | needs: [setup] 39 | services: 40 | localstack: 41 | image: localstack/localstack:2.1.0 42 | ports: 43 | - 4566:4566 44 | - 4510-4559:4510-4559 45 | credentials: 46 | username: ${{ secrets.DOCKERHUB_USERNAME }} 47 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 48 | steps: 49 | - name: Checkout 50 | uses: actions/checkout@v3 51 | with: 52 | path: ./action 53 | 54 | - run: | 55 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 56 | --name "/platform/default/staging/default_ingress_domain" \ 57 | --type "SecureString" \ 58 | --value "example.com" 59 | 60 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 61 | --name "/platform/default/staging/default_alb_ingress_group" \ 62 | --type "SecureString" \ 63 | --value "default" \ 64 | --debug 65 | 66 | env: 67 | AWS_ACCESS_KEY_ID: test 68 | AWS_SECRET_ACCESS_KEY: test 69 | AWS_DEFAULT_REGION: us-east-1 70 | ## Use localhost to connect localstack because the commands runs not in a container 71 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 72 | 73 | - uses: actions/create-github-app-token@v2 74 | id: github-app 75 | with: 76 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 77 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 78 | owner: 'cloudposse-tests' 79 | 80 | - uses: ./action 81 | id: current 82 | with: 83 | cluster: https://github.com/cloudposse-tests/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 84 | toolchain: helm 85 | environment: staging 86 | namespace: staging 87 | path: ./action/test/helm/example-app 88 | application: test-app 89 | ssm-path: platform/default 90 | github-pat: ${{ steps.github-app.outputs.token }} 91 | image: nginx 92 | image-tag: ${{ needs.setup.outputs.random }} 93 | env: 94 | AWS_ACCESS_KEY_ID: test 95 | AWS_SECRET_ACCESS_KEY: test 96 | AWS_DEFAULT_REGION: us-east-1 97 | ## Use localhost to connect localstack because the commands runs not in a container 98 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 99 | ## Use localhost to connect localstack because chamber does not run in a container 100 | CHAMBER_AWS_SSM_ENDPOINT: http://localhost:4566/ 101 | 102 | outputs: 103 | status: ${{ steps.current.outcome }} 104 | result: ${{ steps.current.outputs.webapp-url }} 105 | sha: ${{ steps.current.outputs.sha }} 106 | 107 | assert: 108 | runs-on: ubuntu-latest 109 | environment: terratest 110 | needs: [setup, test] 111 | steps: 112 | - uses: nick-fields/assert-action@v1 113 | with: 114 | expected: "success" 115 | actual: "${{ needs.test.outputs.status }}" 116 | 117 | - uses: nick-fields/assert-action@v1 118 | with: 119 | expected: "https://example-app.example.com/dashboard" 120 | actual: "${{ needs.test.outputs.result }}" 121 | 122 | - uses: nick-fields/assert-action@v1 123 | with: 124 | expected: "" 125 | actual: "${{ needs.test.outputs.sha }}" 126 | comparison: notEqual 127 | 128 | - uses: actions/create-github-app-token@v2 129 | id: github-app 130 | with: 131 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 132 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 133 | owner: 'cloudposse-tests' 134 | 135 | - name: Checkout Argo Configuration 136 | uses: actions/checkout@v3 137 | with: 138 | repository: cloudposse-tests/argocd-deploy-non-prod-test 139 | ref: ${{ needs.test.outputs.sha }} 140 | token: ${{ steps.github-app.outputs.token }} 141 | path: ./assert 142 | 143 | - name: Get Image 144 | id: image 145 | shell: bash 146 | run: |- 147 | image=$( \ 148 | yq eval-all '.spec.template.spec.containers[].image | select(. != null)' \ 149 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 150 | ) 151 | echo "value=${image}" >> $GITHUB_OUTPUT 152 | 153 | - uses: nick-fields/assert-action@v1 154 | with: 155 | expected: "nginx:${{ needs.setup.outputs.random }}" 156 | actual: "${{ steps.image.outputs.value }}" 157 | 158 | - name: Get Ingress 159 | id: ingress 160 | shell: bash 161 | run: |- 162 | ingress=$( \ 163 | yq eval-all 'select(.kind == "Ingress") | .apiVersion' \ 164 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 165 | ) 166 | echo "value=${ingress}" >> $GITHUB_OUTPUT 167 | 168 | - uses: nick-fields/assert-action@v1 169 | with: 170 | expected: "networking.k8s.io/v1" 171 | actual: "${{ steps.ingress.outputs.value }}" 172 | 173 | teardown: 174 | runs-on: ubuntu-latest 175 | needs: [assert] 176 | if: ${{ always() }} 177 | steps: 178 | - name: Tear down 179 | run: echo "Do Tear down" 180 | -------------------------------------------------------------------------------- /.github/workflows/test-destroy.yml: -------------------------------------------------------------------------------- 1 | name: Test - Destroy 2 | on: 3 | # # Uncomment when test added first time to register workflow and comment it back after workflow would be registered 4 | # # 5 | # # Added pull_request to register workflow from the PR. 6 | # # Read more https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo 7 | # pull_request: {} 8 | workflow_dispatch: 9 | inputs: 10 | ref: 11 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 12 | required: false 13 | type: string 14 | sha: 15 | description: "The sha of the commit that triggered the workflow run" 16 | required: false 17 | type: string 18 | 19 | jobs: 20 | setup: 21 | runs-on: ubuntu-latest 22 | services: 23 | localstack: 24 | image: localstack/localstack:2.1.0 25 | ports: 26 | - 4566:4566 27 | - 4510-4559:4510-4559 28 | credentials: 29 | username: ${{ secrets.DOCKERHUB_USERNAME }} 30 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v3 34 | with: 35 | path: ./action 36 | 37 | - run: | 38 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 39 | --name "/platform/default/staging/default_ingress_domain" \ 40 | --type "SecureString" \ 41 | --value "example.com" 42 | 43 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 44 | --name "/platform/default/staging/default_alb_ingress_group" \ 45 | --type "SecureString" \ 46 | --value "default" \ 47 | --debug 48 | 49 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 50 | --name "/platform/default/_metadata/kube_version" \ 51 | --type "SecureString" \ 52 | --value "1.15" \ 53 | --debug 54 | 55 | env: 56 | AWS_ACCESS_KEY_ID: test 57 | AWS_SECRET_ACCESS_KEY: test 58 | AWS_DEFAULT_REGION: us-east-1 59 | ## Use localhost to connect localstack because the commands runs not in a container 60 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 61 | 62 | - id: random 63 | shell: bash 64 | run: |- 65 | echo "password=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 66 | 67 | outputs: 68 | random: ${{ steps.random.outputs.password }} 69 | 70 | 71 | test: 72 | runs-on: ubuntu-latest 73 | environment: terratest 74 | continue-on-error: true 75 | needs: [setup] 76 | services: 77 | localstack: 78 | image: localstack/localstack:2.1.0 79 | ports: 80 | - 4566:4566 81 | - 4510-4559:4510-4559 82 | credentials: 83 | username: ${{ secrets.DOCKERHUB_USERNAME }} 84 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 85 | steps: 86 | - name: Checkout 87 | uses: actions/checkout@v3 88 | with: 89 | path: ./action 90 | 91 | - run: | 92 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 93 | --name "/platform/default/staging/default_ingress_domain" \ 94 | --type "SecureString" \ 95 | --value "example.com" 96 | 97 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 98 | --name "/platform/default/staging/default_alb_ingress_group" \ 99 | --type "SecureString" \ 100 | --value "default" \ 101 | --debug 102 | 103 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 104 | --name "/platform/default/_metadata/kube_version" \ 105 | --type "SecureString" \ 106 | --value "1.15" \ 107 | --debug 108 | 109 | env: 110 | AWS_ACCESS_KEY_ID: test 111 | AWS_SECRET_ACCESS_KEY: test 112 | AWS_DEFAULT_REGION: us-east-1 113 | ## Use localhost to connect localstack because the commands runs not in a container 114 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 115 | 116 | - uses: actions/create-github-app-token@v2 117 | id: github-app 118 | with: 119 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 120 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 121 | owner: 'cloudposse-tests' 122 | 123 | - uses: ./action 124 | id: current 125 | with: 126 | cluster: https://github.com/cloudposse-tests/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 127 | toolchain: helmfile 128 | environment: staging 129 | namespace: staging 130 | path: ./action/test/helmfile/helmfile.yaml 131 | application: test-app 132 | ssm-path: platform/default 133 | github-pat: ${{ steps.github-app.outputs.token }} 134 | image: nginx 135 | image-tag: ${{ needs.setup.outputs.random }} 136 | operation: destroy 137 | env: 138 | AWS_ACCESS_KEY_ID: test 139 | AWS_SECRET_ACCESS_KEY: test 140 | AWS_DEFAULT_REGION: us-east-1 141 | ## Use localhost to connect localstack because the commands runs not in a container 142 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 143 | ## Use localhost to connect localstack because chamber does not run in a container 144 | CHAMBER_AWS_SSM_ENDPOINT: http://localhost:4566/ 145 | 146 | outputs: 147 | sha: ${{ steps.current.outputs.sha }} 148 | 149 | assert: 150 | runs-on: ubuntu-latest 151 | environment: terratest 152 | needs: [setup, test] 153 | steps: 154 | - uses: nick-fields/assert-action@v1 155 | with: 156 | expected: "" 157 | actual: "${{ needs.test.outputs.sha }}" 158 | comparison: notEqual 159 | 160 | - uses: actions/create-github-app-token@v2 161 | id: github-app 162 | with: 163 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 164 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 165 | owner: 'cloudposse-tests' 166 | 167 | - uses: jiangxin/file-exists-action@v1 168 | id: resources 169 | with: 170 | repository: cloudposse-tests/argocd-deploy-non-prod-test 171 | ref: ${{ needs.test.outputs.sha }} 172 | path: plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml 173 | type: file 174 | token: ${{ steps.github-app.outputs.token }} 175 | 176 | - uses: nick-fields/assert-action@v1 177 | with: 178 | expected: "false" 179 | actual: "${{ steps.resources.outputs.exists }}" 180 | 181 | teardown: 182 | runs-on: ubuntu-latest 183 | needs: [assert] 184 | if: ${{ always() }} 185 | steps: 186 | - name: Tear down 187 | run: echo "Do Tear down" 188 | -------------------------------------------------------------------------------- /.github/disabled/test-helm-raw-additional-args.yml: -------------------------------------------------------------------------------- 1 | name: Test - Helm raw with additional args 2 | on: 3 | # # Uncomment when test added first time to register workflow and comment it back after workflow would be registered 4 | # # 5 | # # Added pull_request to register workflow from the PR. 6 | # # Read more https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo 7 | # pull_request: {} 8 | workflow_dispatch: {} 9 | 10 | jobs: 11 | setup: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Setup 15 | run: echo "Do setup" 16 | 17 | - id: random 18 | shell: bash 19 | run: |- 20 | echo "password=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 21 | 22 | outputs: 23 | random: ${{ steps.random.outputs.password }} 24 | 25 | test: 26 | runs-on: ubuntu-latest 27 | continue-on-error: true 28 | needs: [setup] 29 | services: 30 | localstack: 31 | image: localstack/localstack:2.1.0 32 | ports: 33 | - 4566:4566 34 | - 4510-4559:4510-4559 35 | credentials: 36 | username: ${{ secrets.DOCKERHUB_USERNAME }} 37 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 38 | steps: 39 | - name: Checkout 40 | uses: actions/checkout@v3 41 | with: 42 | path: ./action 43 | 44 | - run: | 45 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 46 | --name "/platform/default/staging/default_ingress_domain" \ 47 | --type "SecureString" \ 48 | --value "example.com" 49 | 50 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 51 | --name "/platform/default/staging/default_alb_ingress_group" \ 52 | --type "SecureString" \ 53 | --value "default" \ 54 | --debug 55 | 56 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 57 | --name "/platform/default/_metadata/kube_version" \ 58 | --type "SecureString" \ 59 | --value "1.15" \ 60 | --debug 61 | 62 | env: 63 | AWS_ACCESS_KEY_ID: test 64 | AWS_SECRET_ACCESS_KEY: test 65 | AWS_DEFAULT_REGION: us-east-1 66 | ## Use localhost to connect localstack because the commands runs not in a container 67 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 68 | 69 | - uses: ./action 70 | id: current 71 | with: 72 | cluster: https://github.com/cloudposse-corp/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 73 | toolchain: helm 74 | environment: staging 75 | namespace: staging 76 | path: ./action/test/helm/example-app 77 | application: test-app 78 | ssm-path: platform/default 79 | github-pat: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 80 | image: nginx 81 | image-tag: ${{ needs.setup.outputs.random }} 82 | helm-args: --set foo=${{ needs.setup.outputs.random }} 83 | env: 84 | AWS_ACCESS_KEY_ID: test 85 | AWS_SECRET_ACCESS_KEY: test 86 | AWS_DEFAULT_REGION: us-east-1 87 | ## Use localhost to connect localstack because the commands runs not in a container 88 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 89 | ## Use localhost to connect localstack because chamber does not run in a container 90 | CHAMBER_AWS_SSM_ENDPOINT: http://localhost:4566/ 91 | 92 | outputs: 93 | status: ${{ steps.current.outcome }} 94 | result: ${{ steps.current.outputs.webapp-url }} 95 | sha: ${{ steps.current.outputs.sha }} 96 | 97 | assert: 98 | runs-on: ubuntu-latest 99 | needs: [setup, test] 100 | steps: 101 | - uses: nick-fields/assert-action@v1 102 | with: 103 | expected: "success" 104 | actual: "${{ needs.test.outputs.status }}" 105 | 106 | - uses: nick-fields/assert-action@v1 107 | with: 108 | expected: "https://example-app.example.com/dashboard" 109 | actual: "${{ needs.test.outputs.result }}" 110 | 111 | - uses: nick-fields/assert-action@v1 112 | with: 113 | expected: "" 114 | actual: "${{ needs.test.outputs.sha }}" 115 | comparison: notEqual 116 | 117 | - name: Checkout Argo Configuration 118 | uses: actions/checkout@v3 119 | with: 120 | repository: cloudposse/argocd-deploy-non-prod-test 121 | ref: ${{ needs.test.outputs.sha }} 122 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 123 | path: ./assert 124 | 125 | - name: Get Image 126 | id: image 127 | shell: bash 128 | run: |- 129 | image=$( \ 130 | yq eval-all '.spec.template.spec.containers[].image | select(. != null)' \ 131 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 132 | ) 133 | echo "value=${image}" >> $GITHUB_OUTPUT 134 | 135 | - uses: nick-fields/assert-action@v1 136 | with: 137 | expected: "nginx:${{ needs.setup.outputs.random }}" 138 | actual: "${{ steps.image.outputs.value }}" 139 | 140 | - name: Get Ingress 141 | id: ingress 142 | shell: bash 143 | run: |- 144 | ingress=$( \ 145 | yq eval-all 'select(.kind == "Ingress") | .apiVersion' \ 146 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 147 | ) 148 | echo "value=${ingress}" >> $GITHUB_OUTPUT 149 | 150 | - uses: nick-fields/assert-action@v1 151 | with: 152 | expected: "networking.k8s.io/v1beta1" 153 | actual: "${{ steps.ingress.outputs.value }}" 154 | 155 | - name: Get Name 156 | id: name 157 | shell: bash 158 | run: |- 159 | name=$( \ 160 | yq eval-all '.name' \ 161 | ./assert/plat/ue2-sandbox/apps/staging/test-app/config.yaml \ 162 | ) 163 | echo "value=${name}" >> $GITHUB_OUTPUT 164 | 165 | - uses: nick-fields/assert-action@v1 166 | with: 167 | expected: "staging.test-app" 168 | actual: "${{ steps.name.outputs.value }}" 169 | 170 | - name: Get ConfigMap Data 171 | id: configmap 172 | shell: bash 173 | run: |- 174 | configmap=$( \ 175 | yq eval-all '.data | select(. != null)' \ 176 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 177 | ) 178 | echo "value=${configmap}" >> $GITHUB_OUTPUT 179 | 180 | - uses: nick-fields/assert-action@v1 181 | with: 182 | expected: "foo:${{ needs.setup.outputs.random }}" 183 | actual: "${{ steps.configmap.outputs.value }}" 184 | teardown: 185 | runs-on: ubuntu-latest 186 | needs: [assert] 187 | if: ${{ always() }} 188 | steps: 189 | - name: Tear down 190 | run: echo "Do Tear down" 191 | -------------------------------------------------------------------------------- /.github/workflows/test-helmfile-raw-default-kube-version.yml: -------------------------------------------------------------------------------- 1 | name: Test - Helmfile raw - default kubernetes version 2 | on: 3 | # # Uncomment when test added first time to register workflow and comment it back after workflow would be registered 4 | # # 5 | # # Added pull_request to register workflow from the PR. 6 | # # Read more https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo 7 | # pull_request: {} 8 | workflow_dispatch: 9 | inputs: 10 | ref: 11 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 12 | required: false 13 | type: string 14 | sha: 15 | description: "The sha of the commit that triggered the workflow run" 16 | required: false 17 | type: string 18 | 19 | jobs: 20 | setup: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Setup 24 | run: echo "Do setup" 25 | 26 | - id: random 27 | shell: bash 28 | run: |- 29 | echo "password=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 30 | 31 | outputs: 32 | random: ${{ steps.random.outputs.password }} 33 | 34 | 35 | test: 36 | runs-on: ubuntu-latest 37 | environment: terratest 38 | continue-on-error: true 39 | needs: [setup] 40 | services: 41 | localstack: 42 | image: localstack/localstack:2.1.0 43 | ports: 44 | - 4566:4566 45 | - 4510-4559:4510-4559 46 | credentials: 47 | username: ${{ secrets.DOCKERHUB_USERNAME }} 48 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 49 | steps: 50 | - name: Checkout 51 | uses: actions/checkout@v3 52 | with: 53 | path: ./action 54 | 55 | - run: | 56 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 57 | --name "/platform/default/staging/default_ingress_domain" \ 58 | --type "SecureString" \ 59 | --value "example.com" 60 | 61 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 62 | --name "/platform/default/staging/default_alb_ingress_group" \ 63 | --type "SecureString" \ 64 | --value "default" \ 65 | --debug 66 | 67 | env: 68 | AWS_ACCESS_KEY_ID: test 69 | AWS_SECRET_ACCESS_KEY: test 70 | AWS_DEFAULT_REGION: us-east-1 71 | ## Use localhost to connect localstack because the commands runs not in a container 72 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 73 | 74 | - uses: actions/create-github-app-token@v2 75 | id: github-app 76 | with: 77 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 78 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 79 | owner: 'cloudposse-tests' 80 | 81 | - uses: ./action 82 | id: current 83 | with: 84 | cluster: https://github.com/cloudposse-tests/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 85 | toolchain: helmfile 86 | environment: staging 87 | namespace: staging 88 | path: ./action/test/helmfile/helmfile.yaml 89 | application: test-app 90 | ssm-path: platform/default 91 | github-pat: ${{ steps.github-app.outputs.token }} 92 | image: nginx 93 | image-tag: ${{ needs.setup.outputs.random }} 94 | repository: ${{ github.repository }} 95 | gitref-sha: ${{ github.sha }} 96 | env: 97 | AWS_ACCESS_KEY_ID: test 98 | AWS_SECRET_ACCESS_KEY: test 99 | AWS_DEFAULT_REGION: us-east-1 100 | ## Use localhost to connect localstack because the commands runs not in a container 101 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 102 | ## Use localhost to connect localstack because chamber does not run in a container 103 | CHAMBER_AWS_SSM_ENDPOINT: http://localhost:4566/ 104 | 105 | outputs: 106 | status: ${{ steps.current.outcome }} 107 | result: ${{ steps.current.outputs.webapp-url }} 108 | sha: ${{ steps.current.outputs.sha }} 109 | 110 | assert: 111 | runs-on: ubuntu-latest 112 | environment: terratest 113 | needs: [setup, test] 114 | steps: 115 | - uses: nick-fields/assert-action@v1 116 | with: 117 | expected: "success" 118 | actual: "${{ needs.test.outputs.status }}" 119 | 120 | - uses: nick-fields/assert-action@v1 121 | with: 122 | expected: "https://example-app.example.com/dashboard" 123 | actual: "${{ needs.test.outputs.result }}" 124 | 125 | - uses: nick-fields/assert-action@v1 126 | with: 127 | expected: "" 128 | actual: "${{ needs.test.outputs.sha }}" 129 | comparison: notEqual 130 | 131 | - uses: actions/create-github-app-token@v2 132 | id: github-app 133 | with: 134 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 135 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 136 | owner: 'cloudposse-tests' 137 | 138 | - name: Checkout Argo Configuration 139 | uses: actions/checkout@v3 140 | with: 141 | repository: cloudposse-tests/argocd-deploy-non-prod-test 142 | ref: ${{ needs.test.outputs.sha }} 143 | token: ${{ steps.github-app.outputs.token }} 144 | path: ./assert 145 | 146 | - name: Get Image 147 | id: image 148 | shell: bash 149 | run: |- 150 | image=$( \ 151 | yq eval-all '.spec.template.spec.containers[].image | select(. != null)' \ 152 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 153 | ) 154 | echo "value=${image}" >> $GITHUB_OUTPUT 155 | 156 | - uses: nick-fields/assert-action@v1 157 | with: 158 | expected: "nginx:${{ needs.setup.outputs.random }}" 159 | actual: "${{ steps.image.outputs.value }}" 160 | 161 | - name: Get Ingress 162 | id: ingress 163 | shell: bash 164 | run: |- 165 | ingress=$( \ 166 | yq eval-all 'select(.kind == "Ingress") | .apiVersion' \ 167 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 168 | ) 169 | echo "value=${ingress}" >> $GITHUB_OUTPUT 170 | 171 | - uses: nick-fields/assert-action@v1 172 | with: 173 | expected: "networking.k8s.io/v1" 174 | actual: "${{ steps.ingress.outputs.value }}" 175 | 176 | - name: Get ref 177 | id: app_commit 178 | shell: bash 179 | run: |- 180 | app_commit=$( \ 181 | yq eval-all '.app_commit' \ 182 | ./assert/plat/ue2-sandbox/apps/staging/test-app/config.yaml 183 | ) 184 | echo "value=${app_commit}" >> $GITHUB_OUTPUT 185 | 186 | - uses: nick-fields/assert-action@v1 187 | with: 188 | expected: "${{ github.sha }}" 189 | actual: "${{ steps.app_commit.outputs.value }}" 190 | 191 | teardown: 192 | runs-on: ubuntu-latest 193 | needs: [assert] 194 | if: ${{ always() }} 195 | steps: 196 | - name: Tear down 197 | run: echo "Do Tear down" 198 | -------------------------------------------------------------------------------- /.github/workflows/test-helm-raw.yml: -------------------------------------------------------------------------------- 1 | name: Test - Helm raw 2 | on: 3 | # # Uncomment when test added first time to register workflow and comment it back after workflow would be registered 4 | # # 5 | # # Added pull_request to register workflow from the PR. 6 | # # Read more https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo 7 | # pull_request: {} 8 | workflow_dispatch: 9 | inputs: 10 | ref: 11 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 12 | required: false 13 | type: string 14 | sha: 15 | description: "The sha of the commit that triggered the workflow run" 16 | required: false 17 | type: string 18 | 19 | jobs: 20 | setup: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Setup 24 | run: echo "Do setup" 25 | 26 | - id: random 27 | shell: bash 28 | run: |- 29 | echo "password=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 30 | 31 | outputs: 32 | random: ${{ steps.random.outputs.password }} 33 | 34 | test: 35 | runs-on: ubuntu-latest 36 | environment: terratest 37 | continue-on-error: true 38 | needs: [setup] 39 | services: 40 | localstack: 41 | image: localstack/localstack:2.1.0 42 | ports: 43 | - 4566:4566 44 | - 4510-4559:4510-4559 45 | credentials: 46 | username: ${{ secrets.DOCKERHUB_USERNAME }} 47 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 48 | steps: 49 | - name: Checkout 50 | uses: actions/checkout@v3 51 | with: 52 | path: ./action 53 | 54 | - run: | 55 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 56 | --name "/platform/default/staging/default_ingress_domain" \ 57 | --type "SecureString" \ 58 | --value "example.com" 59 | 60 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 61 | --name "/platform/default/staging/default_alb_ingress_group" \ 62 | --type "SecureString" \ 63 | --value "default" \ 64 | --debug 65 | 66 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 67 | --name "/platform/default/_metadata/kube_version" \ 68 | --type "SecureString" \ 69 | --value "1.15" \ 70 | --debug 71 | 72 | env: 73 | AWS_ACCESS_KEY_ID: test 74 | AWS_SECRET_ACCESS_KEY: test 75 | AWS_DEFAULT_REGION: us-east-1 76 | ## Use localhost to connect localstack because the commands runs not in a container 77 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 78 | 79 | - uses: actions/create-github-app-token@v2 80 | id: github-app 81 | with: 82 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 83 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 84 | owner: 'cloudposse-tests' 85 | 86 | - uses: ./action 87 | id: current 88 | with: 89 | cluster: https://github.com/cloudposse-tests/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 90 | toolchain: helm 91 | environment: staging 92 | namespace: staging 93 | path: ./action/test/helm/example-app 94 | application: test-app 95 | ssm-path: platform/default 96 | github-pat: ${{ steps.github-app.outputs.token }} 97 | image: nginx 98 | image-tag: ${{ needs.setup.outputs.random }} 99 | env: 100 | AWS_ACCESS_KEY_ID: test 101 | AWS_SECRET_ACCESS_KEY: test 102 | AWS_DEFAULT_REGION: us-east-1 103 | ## Use localhost to connect localstack because the commands runs not in a container 104 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 105 | ## Use localhost to connect localstack because chamber does not run in a container 106 | CHAMBER_AWS_SSM_ENDPOINT: http://localhost:4566/ 107 | 108 | outputs: 109 | status: ${{ steps.current.outcome }} 110 | result: ${{ steps.current.outputs.webapp-url }} 111 | sha: ${{ steps.current.outputs.sha }} 112 | 113 | assert: 114 | runs-on: ubuntu-latest 115 | environment: terratest 116 | needs: [setup, test] 117 | steps: 118 | - uses: nick-fields/assert-action@v1 119 | with: 120 | expected: "success" 121 | actual: "${{ needs.test.outputs.status }}" 122 | 123 | - uses: nick-fields/assert-action@v1 124 | with: 125 | expected: "https://example-app.example.com/dashboard" 126 | actual: "${{ needs.test.outputs.result }}" 127 | 128 | - uses: nick-fields/assert-action@v1 129 | with: 130 | expected: "" 131 | actual: "${{ needs.test.outputs.sha }}" 132 | comparison: notEqual 133 | 134 | - uses: actions/create-github-app-token@v2 135 | id: github-app 136 | with: 137 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 138 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 139 | owner: 'cloudposse-tests' 140 | 141 | - name: Checkout Argo Configuration 142 | uses: actions/checkout@v3 143 | with: 144 | repository: cloudposse-tests/argocd-deploy-non-prod-test 145 | ref: ${{ needs.test.outputs.sha }} 146 | token: ${{ steps.github-app.outputs.token }} 147 | path: ./assert 148 | 149 | - name: Get Image 150 | id: image 151 | shell: bash 152 | run: |- 153 | image=$( \ 154 | yq eval-all '.spec.template.spec.containers[].image | select(. != null)' \ 155 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 156 | ) 157 | echo "value=${image}" >> $GITHUB_OUTPUT 158 | 159 | - uses: nick-fields/assert-action@v1 160 | with: 161 | expected: "nginx:${{ needs.setup.outputs.random }}" 162 | actual: "${{ steps.image.outputs.value }}" 163 | 164 | - name: Get Ingress 165 | id: ingress 166 | shell: bash 167 | run: |- 168 | ingress=$( \ 169 | yq eval-all 'select(.kind == "Ingress") | .apiVersion' \ 170 | ./assert/plat/ue2-sandbox/apps/staging/test-app/manifests/resources.yaml \ 171 | ) 172 | echo "value=${ingress}" >> $GITHUB_OUTPUT 173 | 174 | - uses: nick-fields/assert-action@v1 175 | with: 176 | expected: "networking.k8s.io/v1beta1" 177 | actual: "${{ steps.ingress.outputs.value }}" 178 | 179 | - name: Get Name 180 | id: name 181 | shell: bash 182 | run: |- 183 | name=$( \ 184 | yq eval-all '.name' \ 185 | ./assert/plat/ue2-sandbox/apps/staging/test-app/config.yaml \ 186 | ) 187 | echo "value=${name}" >> $GITHUB_OUTPUT 188 | 189 | - uses: nick-fields/assert-action@v1 190 | with: 191 | expected: "staging.test-app" 192 | actual: "${{ steps.name.outputs.value }}" 193 | 194 | teardown: 195 | runs-on: ubuntu-latest 196 | needs: [assert] 197 | if: ${{ always() }} 198 | steps: 199 | - name: Tear down 200 | run: echo "Do Tear down" 201 | -------------------------------------------------------------------------------- /.github/workflows/test-helmfile-raw.yml: -------------------------------------------------------------------------------- 1 | name: Test - Helmfile raw 2 | on: 3 | # # Uncomment when test added first time to register workflow and comment it back after workflow would be registered 4 | # # 5 | # # Added pull_request to register workflow from the PR. 6 | # # Read more https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo 7 | # pull_request: {} 8 | workflow_dispatch: 9 | inputs: 10 | ref: 11 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 12 | required: false 13 | type: string 14 | sha: 15 | description: "The sha of the commit that triggered the workflow run" 16 | required: false 17 | type: string 18 | 19 | jobs: 20 | setup: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Setup 24 | run: echo "Do setup" 25 | 26 | - id: random 27 | shell: bash 28 | run: |- 29 | echo "password=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 30 | echo "environment=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 31 | 32 | outputs: 33 | random: ${{ steps.random.outputs.password }} 34 | environment: ${{ steps.random.outputs.environment }} 35 | 36 | 37 | test: 38 | runs-on: ubuntu-latest 39 | environment: terratest 40 | continue-on-error: true 41 | needs: [setup] 42 | services: 43 | localstack: 44 | image: localstack/localstack:2.1.0 45 | ports: 46 | - 4566:4566 47 | - 4510-4559:4510-4559 48 | credentials: 49 | username: ${{ secrets.DOCKERHUB_USERNAME }} 50 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 51 | steps: 52 | - name: Checkout 53 | uses: actions/checkout@v3 54 | with: 55 | path: ./action 56 | 57 | - run: | 58 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 59 | --name "/platform/default/${{ needs.setup.outputs.environment }}/default_ingress_domain" \ 60 | --type "SecureString" \ 61 | --value "example.com" 62 | 63 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 64 | --name "/platform/default/${{ needs.setup.outputs.environment }}/default_alb_ingress_group" \ 65 | --type "SecureString" \ 66 | --value "default" \ 67 | --debug 68 | 69 | aws ${AWS_ENDPOINT_OVERRIDE:+--endpoint-url $AWS_ENDPOINT_OVERRIDE} ssm put-parameter \ 70 | --name "/platform/default/_metadata/kube_version" \ 71 | --type "SecureString" \ 72 | --value "1.15" \ 73 | --debug 74 | 75 | env: 76 | AWS_ACCESS_KEY_ID: test 77 | AWS_SECRET_ACCESS_KEY: test 78 | AWS_DEFAULT_REGION: us-east-1 79 | ## Use localhost to connect localstack because the commands runs not in a container 80 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 81 | 82 | - uses: actions/create-github-app-token@v2 83 | id: github-app 84 | with: 85 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 86 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 87 | owner: 'cloudposse-tests' 88 | 89 | - uses: ./action 90 | id: current 91 | with: 92 | cluster: https://github.com/cloudposse-tests/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 93 | toolchain: helmfile 94 | environment: ${{ needs.setup.outputs.environment }} 95 | namespace: ${{ needs.setup.outputs.environment }} 96 | path: ./action/test/helmfile/helmfile.yaml 97 | application: test-app 98 | ssm-path: platform/default 99 | github-pat: ${{ steps.github-app.outputs.token }} 100 | image: nginx 101 | image-tag: ${{ needs.setup.outputs.random }} 102 | synchronously: true 103 | repository: ${{ github.repository }} 104 | ref: ${{ github.sha }} 105 | env: 106 | AWS_ACCESS_KEY_ID: test 107 | AWS_SECRET_ACCESS_KEY: test 108 | AWS_DEFAULT_REGION: us-east-1 109 | ## Use localhost to connect localstack because the commands runs not in a container 110 | AWS_ENDPOINT_OVERRIDE: http://localhost:4566 111 | ## Use localhost to connect localstack because chamber does not run in a container 112 | CHAMBER_AWS_SSM_ENDPOINT: http://localhost:4566/ 113 | 114 | outputs: 115 | status: ${{ steps.current.outcome }} 116 | result: ${{ steps.current.outputs.webapp-url }} 117 | sha: ${{ steps.current.outputs.sha }} 118 | 119 | argocd: 120 | runs-on: ubuntu-latest 121 | environment: terratest 122 | needs: [setup] 123 | steps: 124 | - uses: actions/create-github-app-token@v2 125 | id: github-app 126 | with: 127 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 128 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 129 | owner: 'cloudposse-tests' 130 | 131 | - name: Checkout Argo Configuration 132 | uses: actions/checkout@v3 133 | with: 134 | repository: cloudposse-tests/argocd-deploy-non-prod-test 135 | token: ${{ steps.github-app.outputs.token }} 136 | path: ./status 137 | 138 | - name: wait-for-commit 139 | id: wait 140 | shell: bash 141 | run: | 142 | echo "Wait for commit" 143 | 144 | SEEK_MESSAGE="Deploy cloudposse/github-action-deploy-argocd SHA ${{ github.sha }} RUN ${{ github.run_id }} ATEMPT ${{ github.run_attempt }}" 145 | echo ${SEEK_MESSAGE} 146 | 147 | cd ./status 148 | 149 | max_iterations=50 150 | wait_seconds=10 151 | 152 | iterations=0 153 | while true 154 | do 155 | iterations=$((iterations+1)) 156 | echo "Attempt $iterations" 157 | sleep $wait_seconds 158 | 159 | set +e 160 | git pull 161 | git log --format=%B -n 50 | grep "${SEEK_MESSAGE}" 162 | COMMIT_APPEARS=$? 163 | set -e 164 | 165 | if [ $COMMIT_APPEARS -eq 0 ]; then 166 | echo "Commit appers" 167 | break 168 | fi 169 | 170 | if [ "$iterations" -ge "$max_iterations" ]; then 171 | echo "Loop Timeout" 172 | exit 1 173 | fi 174 | done 175 | 176 | SHA=$(git log --format=oneline -n 50 | grep "${SEEK_MESSAGE}" | cut -d' ' -f1 | head -1) 177 | 178 | echo "sha=${SHA}" >> $GITHUB_OUTPUT 179 | 180 | - name: set status 181 | uses: myrotvorets/set-commit-status-action@master 182 | with: 183 | repo: ${{ github.repository }} 184 | sha: ${{ github.sha }} 185 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 186 | status: success 187 | context: continuous-delivery/${{ needs.setup.outputs.environment }}.test-app 188 | 189 | assert: 190 | runs-on: ubuntu-latest 191 | environment: terratest 192 | needs: [setup, test, argocd] 193 | steps: 194 | - uses: nick-fields/assert-action@v1 195 | with: 196 | expected: "success" 197 | actual: "${{ needs.test.outputs.status }}" 198 | 199 | - uses: nick-fields/assert-action@v1 200 | with: 201 | expected: "https://example-app.example.com/dashboard" 202 | actual: "${{ needs.test.outputs.result }}" 203 | 204 | - uses: nick-fields/assert-action@v1 205 | with: 206 | expected: "" 207 | actual: "${{ needs.test.outputs.sha }}" 208 | comparison: notEqual 209 | 210 | - uses: actions/create-github-app-token@v2 211 | id: github-app 212 | with: 213 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 214 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 215 | owner: 'cloudposse-tests' 216 | 217 | - name: Checkout Argo Configuration 218 | uses: actions/checkout@v3 219 | with: 220 | repository: cloudposse-tests/argocd-deploy-non-prod-test 221 | ref: ${{ needs.test.outputs.sha }} 222 | token: ${{ steps.github-app.outputs.token }} 223 | path: ./assert 224 | 225 | - name: Get Image 226 | id: image 227 | shell: bash 228 | run: |- 229 | image=$( \ 230 | yq eval-all '.spec.template.spec.containers[].image | select(. != null)' \ 231 | ./assert/plat/ue2-sandbox/apps/${{ needs.setup.outputs.environment }}/test-app/manifests/resources.yaml \ 232 | ) 233 | echo "value=${image}" >> $GITHUB_OUTPUT 234 | 235 | - uses: nick-fields/assert-action@v1 236 | with: 237 | expected: "nginx:${{ needs.setup.outputs.random }}" 238 | actual: "${{ steps.image.outputs.value }}" 239 | 240 | - name: Get Ingress 241 | id: ingress 242 | shell: bash 243 | run: |- 244 | ingress=$( \ 245 | yq eval-all 'select(.kind == "Ingress") | .apiVersion' \ 246 | ./assert/plat/ue2-sandbox/apps/${{ needs.setup.outputs.environment }}/test-app/manifests/resources.yaml \ 247 | ) 248 | echo "value=${ingress}" >> $GITHUB_OUTPUT 249 | 250 | - uses: nick-fields/assert-action@v1 251 | with: 252 | expected: "networking.k8s.io/v1beta1" 253 | actual: "${{ steps.ingress.outputs.value }}" 254 | 255 | - name: Get Name 256 | id: name 257 | shell: bash 258 | run: |- 259 | name=$( \ 260 | yq eval-all '.name' \ 261 | ./assert/plat/ue2-sandbox/apps/${{ needs.setup.outputs.environment }}/test-app/config.yaml \ 262 | ) 263 | echo "value=${name}" >> $GITHUB_OUTPUT 264 | 265 | - uses: nick-fields/assert-action@v1 266 | with: 267 | expected: "${{ needs.setup.outputs.environment }}.test-app" 268 | actual: "${{ steps.name.outputs.value }}" 269 | 270 | 271 | - name: Get ref 272 | id: app_commit 273 | shell: bash 274 | run: |- 275 | app_commit=$( \ 276 | yq eval-all '.app_commit' \ 277 | ./assert/plat/ue2-sandbox/apps/${{ needs.setup.outputs.environment }}/test-app/config.yaml \ 278 | ) 279 | echo "value=${app_commit}" >> $GITHUB_OUTPUT 280 | 281 | - uses: nick-fields/assert-action@v1 282 | with: 283 | expected: "${{ github.sha }}" 284 | actual: "${{ steps.app_commit.outputs.value }}" 285 | 286 | 287 | teardown: 288 | runs-on: ubuntu-latest 289 | needs: [assert] 290 | if: ${{ always() }} 291 | steps: 292 | - name: Tear down 293 | run: echo "Do Tear down" 294 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Project Banner
5 | 6 | 7 |

Latest ReleaseLast UpdatedSlack Community 8 | 9 |

10 | 11 | 12 | 32 | 33 | Deploy on Kubernetes with ArgoCD 34 | 35 | 36 | 37 | 38 | ## Introduction 39 | 40 | Deploy on Kubernetes with Helm/HelmFile and ArgoCD. 41 | 42 | 43 | 44 | 45 | ## Usage 46 | 47 | Deploy environment 48 | ```yaml 49 | name: Pull Request 50 | on: 51 | pull_request: 52 | branches: [ 'main' ] 53 | types: [opened, synchronize, reopened] 54 | 55 | jobs: 56 | deploy: 57 | runs-on: ubuntu-latest 58 | environment: 59 | name: preview 60 | url: ${{ steps.deploy.outputs.webapp-url }} 61 | steps: 62 | 63 | - name: Configure AWS Credentials 64 | uses: aws-actions/configure-aws-credentials@v1.7.0 65 | with: 66 | aws-region: us-west-2 67 | role-to-assume: arn:aws:iam::111111111111:role/preview 68 | role-session-name: deploy 69 | 70 | - name: Deploy 71 | uses: cloudposse/github-action-deploy-argocd@main 72 | id: deploy 73 | with: 74 | cluster: https://github.com/cloudposse/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 75 | toolchain: helmfile 76 | environment: preview 77 | namespace: preview 78 | application: test-app 79 | github-pat: ${{ secrets.GITHUB_AUTH_PAT }} 80 | repository: ${{ github.repository }} 81 | ref: ${{ github.event.pull_request.head.ref }} 82 | image: nginx 83 | image-tag: latest 84 | operation: deploy 85 | debug: false 86 | synchronously: true 87 | ``` 88 | 89 | 90 | Destroy environment 91 | ```yaml 92 | name: Pull Request 93 | on: 94 | pull_request: 95 | branches: [ 'main' ] 96 | types: [closed] 97 | 98 | jobs: 99 | destroy: 100 | runs-on: ubuntu-latest 101 | steps: 102 | - name: Configure AWS Credentials 103 | uses: aws-actions/configure-aws-credentials@v1.7.0 104 | with: 105 | aws-region: us-west-2 106 | role-to-assume: arn:aws:iam::111111111111:role/preview 107 | role-session-name: destroy 108 | 109 | - name: Destroy 110 | uses: cloudposse/github-action-deploy-helmfile@main 111 | id: destroy 112 | with: 113 | cluster: https://github.com/cloudposse/argocd-deploy-non-prod-test/blob/main/plat/ue2-sandbox/apps 114 | toolchain: helmfile 115 | environment: preview 116 | namespace: preview 117 | application: test-app 118 | github-pat: ${{ secrets.GITHUB_AUTH_PAT }} 119 | repository: ${{ github.repository }} 120 | ref: ${{ github.event.pull_request.head.ref }} 121 | image: "" 122 | image-tag: "" 123 | operation: destroy 124 | debug: false 125 | ``` 126 | 127 | 128 | 129 | 130 | 131 | 132 | ## Inputs 133 | 134 | | Name | Description | Default | Required | 135 | |------|-------------|---------|----------| 136 | | application | Application name | N/A | true | 137 | | aws-region | AWS region | us-east-1 | false | 138 | | check-retry-count | Check retry count (for synchronously mode) | 5 | false | 139 | | check-retry-interval | Check retry interval (in seconds) (for synchronously mode) | 10 | false | 140 | | cluster | Cluster name | N/A | true | 141 | | commit-retry-count | Commit retry count | 4 | false | 142 | | commit-retry-interval | Commit retry interval (in seconds) | 10 | false | 143 | | commit-status-github-token | Github token to access the app repository. Defaults to github-pat if not set. | N/A | false | 144 | | commit-timeout | Commit timeout (in seconds) | 60 | false | 145 | | debug | Debug mode | false | false | 146 | | environment | Helmfile environment | preview | false | 147 | | github-pat | Github PAT to access argocd configuration repository | N/A | true | 148 | | gitref-sha | Git SHA (Depricated. Use `ref` instead) | | false | 149 | | helm-args | Additional helm arguments | | false | 150 | | helm-dependency-build | Run helm dependency build, only for helm toolchain, `true` or `false` | false | false | 151 | | helm-version | Helm version | v3.10.2 | false | 152 | | helmfile-args | Additional helmfile arguments | | false | 153 | | helmfile-version | Helmfile version | v0.148.1 | false | 154 | | image | Docker image | N/A | true | 155 | | image-tag | Docker image tag | N/A | true | 156 | | namespace | Kubernetes namespace | N/A | true | 157 | | operation | Operation with helmfiles. (valid options - `deploy`, `destroy`) | deploy | true | 158 | | path | The path where lives the helmfile or helm chart. | N/A | true | 159 | | ref | Git ref | N/A | true | 160 | | release\_label\_name | The name of the label used to describe the helm release | release | false | 161 | | repository | Application GitHub repository full name | N/A | true | 162 | | ssm-path | SSM path to read environment secrets | N/A | true | 163 | | synchronously | Wait until ArgoCD successfully apply the changes | false | false | 164 | | toolchain | Toolchain ('helm', 'helmfile') | helmfile | false | 165 | | values\_file | Helm values file, this can be a single file or a comma separated list of files | | false | 166 | 167 | 168 | 169 | ## Outputs 170 | 171 | | Name | Description | 172 | |------|-------------| 173 | | sha | Git commit SHA into argocd repo | 174 | | webapp-url | Web Application url | 175 | 176 | 177 | 178 | 179 | 180 | ## Related Projects 181 | 182 | Check out these related projects. 183 | 184 | 185 | 186 | ## References 187 | 188 | For additional context, refer to some of these links. 189 | 190 | - [github-actions-workflows](https://github.com/cloudposse/github-actions-workflows) - Reusable workflows for different types of projects 191 | 192 | 193 | 194 | 195 | ## ✨ Contributing 196 | 197 | This project is under active development, and we encourage contributions from our community. 198 | 199 | 200 | 201 | Many thanks to our outstanding contributors: 202 | 203 | 204 | 205 | 206 | 207 | For 🐛 bug reports & feature requests, please use the [issue tracker](https://github.com/cloudposse/github-action-deploy-argocd/issues). 208 | 209 | In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. 210 | 1. Review our [Code of Conduct](https://github.com/cloudposse/github-action-deploy-argocd/?tab=coc-ov-file#code-of-conduct) and [Contributor Guidelines](https://github.com/cloudposse/.github/blob/main/CONTRIBUTING.md). 211 | 2. **Fork** the repo on GitHub 212 | 3. **Clone** the project to your own machine 213 | 4. **Commit** changes to your own branch 214 | 5. **Push** your work back up to your fork 215 | 6. Submit a **Pull Request** so that we can review your changes 216 | 217 | **NOTE:** Be sure to merge the latest changes from "upstream" before making a pull request! 218 | 219 | 220 | ## Running Terraform Tests 221 | 222 | We use [Atmos](https://atmos.tools) to streamline how Terraform tests are run. It centralizes configuration and wraps common test workflows with easy-to-use commands. 223 | 224 | All tests are located in the [`test/`](test) folder. 225 | 226 | Under the hood, tests are powered by Terratest together with our internal [Test Helpers](https://github.com/cloudposse/test-helpers) library, providing robust infrastructure validation. 227 | 228 | Setup dependencies: 229 | - Install Atmos ([installation guide](https://atmos.tools/install/)) 230 | - Install Go [1.24+ or newer](https://go.dev/doc/install) 231 | - Install Terraform or OpenTofu 232 | 233 | To run tests: 234 | 235 | - Run all tests: 236 | ```sh 237 | atmos test run 238 | ``` 239 | - Clean up test artifacts: 240 | ```sh 241 | atmos test clean 242 | ``` 243 | - Explore additional test options: 244 | ```sh 245 | atmos test --help 246 | ``` 247 | The configuration for test commands is centrally managed. To review what's being imported, see the [`atmos.yaml`](https://raw.githubusercontent.com/cloudposse/.github/refs/heads/main/.github/atmos/terraform-module.yaml) file. 248 | 249 | Learn more about our [automated testing in our documentation](https://docs.cloudposse.com/community/contribute/automated-testing/) or implementing [custom commands](https://atmos.tools/core-concepts/custom-commands/) with atmos. 250 | 251 | ### 🌎 Slack Community 252 | 253 | Join our [Open Source Community](https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/github-action-deploy-argocd&utm_content=slack) on Slack. It's **FREE** for everyone! Our "SweetOps" community is where you get to talk with others who share a similar vision for how to rollout and manage infrastructure. This is the best place to talk shop, ask questions, solicit feedback, and work together as a community to build totally *sweet* infrastructure. 254 | 255 | ### 📰 Newsletter 256 | 257 | Sign up for [our newsletter](https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/github-action-deploy-argocd&utm_content=newsletter) and join 3,000+ DevOps engineers, CTOs, and founders who get insider access to the latest DevOps trends, so you can always stay in the know. 258 | Dropped straight into your Inbox every week — and usually a 5-minute read. 259 | 260 | ### 📆 Office Hours 261 | 262 | [Join us every Wednesday via Zoom](https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/github-action-deploy-argocd&utm_content=office_hours) for your weekly dose of insider DevOps trends, AWS news and Terraform insights, all sourced from our SweetOps community, plus a _live Q&A_ that you can’t find anywhere else. 263 | It's **FREE** for everyone! 264 | ## License 265 | 266 | License 267 | 268 |
269 | Preamble to the Apache License, Version 2.0 270 |
271 |
272 | 273 | Complete license is available in the [`LICENSE`](LICENSE) file. 274 | 275 | ```text 276 | Licensed to the Apache Software Foundation (ASF) under one 277 | or more contributor license agreements. See the NOTICE file 278 | distributed with this work for additional information 279 | regarding copyright ownership. The ASF licenses this file 280 | to you under the Apache License, Version 2.0 (the 281 | "License"); you may not use this file except in compliance 282 | with the License. You may obtain a copy of the License at 283 | 284 | https://www.apache.org/licenses/LICENSE-2.0 285 | 286 | Unless required by applicable law or agreed to in writing, 287 | software distributed under the License is distributed on an 288 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 289 | KIND, either express or implied. See the License for the 290 | specific language governing permissions and limitations 291 | under the License. 292 | ``` 293 |
294 | 295 | ## Trademarks 296 | 297 | All other trademarks referenced herein are the property of their respective owners. 298 | 299 | 300 | --- 301 | Copyright © 2017-2025 [Cloud Posse, LLC](https://cpco.io/copyright) 302 | 303 | 304 | README footer 305 | 306 | Beacon 307 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Deploy ArgoCD' 2 | description: 'Deploy on Kubernetes with ArgoCD' 3 | author: hello@cloudposse.com 4 | branding: 5 | icon: 'cpu' 6 | color: 'white' 7 | inputs: 8 | cluster: 9 | description: Cluster name 10 | required: true 11 | aws-region: 12 | description: AWS region 13 | required: false 14 | default: us-east-1 15 | path: 16 | description: The path where lives the helmfile or helm chart. 17 | required: true 18 | toolchain: 19 | description: Toolchain ('helm', 'helmfile') 20 | required: false 21 | default: helmfile 22 | ssm-path: 23 | required: true 24 | description: SSM path to read environment secrets 25 | operation: 26 | description: Operation with helmfiles. (valid options - `deploy`, `destroy`) 27 | required: true 28 | default: deploy 29 | environment: 30 | description: Helmfile environment 31 | required: false 32 | default: preview 33 | repository: 34 | description: Application GitHub repository full name 35 | required: true 36 | ref: 37 | description: Git ref 38 | required: true 39 | gitref-sha: 40 | description: Git SHA (Depricated. Use `ref` instead) 41 | required: false 42 | default: '' 43 | namespace: 44 | description: Kubernetes namespace 45 | required: true 46 | application: 47 | description: Application name 48 | required: true 49 | image: 50 | description: Docker image 51 | required: true 52 | image-tag: 53 | description: Docker image tag 54 | required: true 55 | debug: 56 | description: Debug mode 57 | default: 'false' 58 | required: false 59 | values_file: 60 | description: Helm values file, this can be a single file or a comma separated list of files 61 | default: "" 62 | required: false 63 | release_label_name: 64 | description: The name of the label used to describe the helm release 65 | default: "release" 66 | required: false 67 | github-pat: 68 | description: Github PAT to access argocd configuration repository 69 | required: true 70 | commit-status-github-token: 71 | description: Github token to access the app repository. Defaults to github-pat if not set. 72 | required: false 73 | synchronously: 74 | description: "Wait until ArgoCD successfully apply the changes" 75 | default: 'false' 76 | check-retry-count: 77 | description: 'Check retry count (for synchronously mode)' 78 | required: false 79 | default: "5" 80 | check-retry-interval: 81 | description: 'Check retry interval (in seconds) (for synchronously mode)' 82 | required: false 83 | default: "10" 84 | commit-retry-count: 85 | description: 'Commit retry count' 86 | required: false 87 | default: "4" 88 | commit-retry-interval: 89 | description: 'Commit retry interval (in seconds)' 90 | required: false 91 | default: "10" 92 | commit-timeout: 93 | description: 'Commit timeout (in seconds)' 94 | required: false 95 | default: "60" 96 | helm-dependency-build: 97 | description: 'Run helm dependency build, only for helm toolchain, `true` or `false`' 98 | required: false 99 | default: "false" 100 | helm-args: 101 | description: 'Additional helm arguments' 102 | required: false 103 | default: "" 104 | helmfile-args: 105 | description: 'Additional helmfile arguments' 106 | required: false 107 | default: "" 108 | helm-version: 109 | description: "Helm version" 110 | required: false 111 | default: "v3.10.2" 112 | helmfile-version: 113 | description: "Helmfile version" 114 | required: false 115 | default: "v0.148.1" 116 | outputs: 117 | webapp-url: 118 | description: "Web Application url" 119 | value: ${{ steps.result.outputs.webapp_url }} 120 | sha: 121 | description: "Git commit SHA into argocd repo" 122 | value: ${{ steps.git.outputs.sha }} 123 | runs: 124 | using: "composite" 125 | steps: 126 | - name: Setup yq 127 | uses: dcarbone/install-yq-action@v1.1.0 128 | with: 129 | version: v4.28.1 130 | download-compressed: true 131 | force: true 132 | 133 | - name: Setup helmfile 134 | uses: mamezou-tech/setup-helmfile@v1.2.0 135 | if: ${{ inputs.operation == 'deploy' }} 136 | with: 137 | helmfile-version: "${{ inputs.helmfile-version }}" 138 | helm-version: "${{ inputs.helm-version }}" 139 | install-kubectl: false 140 | 141 | - name: Setup node 142 | uses: actions/setup-node@v4 143 | with: 144 | node-version: 20 145 | 146 | - name: Install git-url-parse 147 | shell: bash 148 | run: npm install git-url-parse@14.0.0 149 | 150 | - name: Parse git URL for destination 151 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1, node 20 152 | id: destination 153 | with: 154 | script: | 155 | const GitUrlParse = require("git-url-parse"); 156 | function run(url) { 157 | try { 158 | console.log("url: %s", url) 159 | const urlObj = GitUrlParse(url); 160 | core.setOutput('result', JSON.stringify(urlObj)); 161 | const keys = Object.keys(urlObj); 162 | keys.forEach(key=>{ 163 | if(typeof urlObj[key] === 'string' || urlObj[key] === null){ 164 | core.setOutput(key, urlObj[key]); 165 | } 166 | }) 167 | } 168 | catch (error) { 169 | core.setFailed(error.message); 170 | } 171 | } 172 | run("${{ inputs.cluster }}") 173 | 174 | - id: destination_dir 175 | shell: bash 176 | run: |- 177 | echo "name=$(echo $RANDOM | md5sum | head -c 20)" >> $GITHUB_OUTPUT 178 | 179 | - name: Config 180 | id: config 181 | uses: cloudposse/github-action-yaml-config-query@0.1.3 182 | with: 183 | config: |- 184 | tmp: ./tmp/${{ steps.destination.outputs.filepath }}/${{ inputs.namespace }}/${{ inputs.application }} 185 | path: ${{ steps.destination.outputs.filepath }}/${{ inputs.namespace }}/${{ inputs.application }} 186 | 187 | - name: Checkout Argo Configuration 188 | uses: actions/checkout@v3 189 | with: 190 | repository: ${{ steps.destination.outputs.owner }}/${{ steps.destination.outputs.name }} 191 | ref: ${{ steps.destination.outputs.ref }} 192 | token: ${{ inputs.github-pat }} 193 | path: ${{ steps.destination_dir.outputs.name }} 194 | 195 | - name: Setup chamber 196 | if: ${{ inputs.operation == 'deploy' }} 197 | shell: bash 198 | env: 199 | version: v2.14.1 200 | run: | 201 | set -x 202 | os=$(uname -s | tr '[:upper:]' '[:lower:]') 203 | arch="" 204 | case $(uname -m) in 205 | x86_64) 206 | arch="amd64" 207 | ;; 208 | aarch64) 209 | arch="arm64" 210 | ;; 211 | arch64) 212 | arch="arm64" 213 | ;; 214 | *) 215 | echo "Unsupported architecture $(uname -m)" 216 | exit 1 217 | ;; 218 | esac 219 | curl -LOs https://github.com/segmentio/chamber/releases/download/${version}/chamber-${version}-${os}-${arch} 220 | sudo install chamber-${version}-${os}-${arch} /usr/local/bin/chamber 221 | 222 | - name: Read platform context 223 | if: ${{ inputs.operation == 'deploy' }} 224 | shell: bash 225 | run: | 226 | chamber --verbose export ${{ inputs.ssm-path }}/${{ inputs.environment }} --format yaml --output-file ./platform.yaml 227 | 228 | - name: YQ Platform settings 229 | if: ${{ inputs.operation == 'deploy' }} 230 | shell: bash 231 | run: | 232 | sudo chmod 777 ./platform.yaml 233 | yq --exit-status --no-colors --inplace eval '{"platform": .}' ./platform.yaml 234 | 235 | - name: Read platform metadata 236 | if: ${{ inputs.operation == 'deploy' }} 237 | shell: bash 238 | run: | 239 | chamber --verbose export ${{ inputs.ssm-path }}/_metadata --format yaml --output-file ./_metadata.yaml 240 | 241 | - name: YQ Platform settings 242 | if: ${{ inputs.operation == 'deploy' }} 243 | shell: bash 244 | id: metadata 245 | run: | 246 | for output in $(yq --exit-status --no-colors eval-all '. | to_entries | map( .key + "=" + .value ) | join("\n")' ./_metadata.yaml); do 247 | echo "${output}" >> $GITHUB_OUTPUT ; 248 | done 249 | 250 | - name: Context 251 | if: ${{ inputs.operation == 'deploy' }} 252 | id: arguments 253 | uses: cloudposse/github-action-yaml-config-query@0.1.3 254 | with: 255 | query: .${{ steps.metadata.outputs.kube_version == '' }} 256 | config: |- 257 | true: 258 | kube_version: "" 259 | false: 260 | kube_version: --kube-version=${{ steps.metadata.outputs.kube_version }} 261 | 262 | 263 | - name: Ensure argocd repo structure 264 | if: ${{ inputs.operation == 'deploy' }} 265 | shell: bash 266 | run: | 267 | mkdir -p ${{ steps.config.outputs.tmp }}/manifests 268 | 269 | - name: Helmfile render 270 | if: ${{ inputs.toolchain == 'helmfile' && inputs.operation == 'deploy' }} 271 | shell: bash 272 | run: | 273 | helmfile --namespace ${{ inputs.namespace }} \ 274 | --environment ${{ inputs.environment }} \ 275 | --file ${{ inputs.path}} \ 276 | --state-values-file $(pwd)/platform.yaml \ 277 | template \ 278 | --args="${{ steps.arguments.outputs.kube_version }}" \ 279 | ${{ inputs.helmfile-args }} > ${{ steps.config.outputs.tmp }}/manifests/resources.yaml 280 | env: 281 | IMAGE_NAME: ${{ inputs.image }} 282 | IMAGE_TAG: ${{ inputs.image-tag }} 283 | 284 | - name: Build Helm Dependencies 285 | if: ${{ inputs.toolchain == 'helm' && inputs.operation == 'deploy' && inputs.helm-dependency-build == 'true'}} 286 | shell: bash 287 | run: | 288 | helm dependency build ${{ inputs.path }} 289 | 290 | - name: Helm raw render 291 | if: ${{ inputs.toolchain == 'helm' && inputs.operation == 'deploy' }} 292 | shell: bash 293 | run: | 294 | IFS=', ' read -r -a array <<< "${{ inputs.values_file }}" 295 | for element in ${array[@]}; do VALUES_STR+="--values $element "; done 296 | 297 | helm template ${{ inputs.application }} ${{ inputs.path }} \ 298 | --set image.repository=${{ inputs.image }} \ 299 | --set global.image.repository=${{ inputs.image }} \ 300 | --set image.tag=${{ inputs.image-tag }} \ 301 | --set global.image.tag=${{ inputs.image-tag }} \ 302 | --set environment=${{ inputs.environment }} \ 303 | --create-namespace=true \ 304 | --namespace ${{ inputs.namespace }} \ 305 | --set ingress.default.hosts.example=test \ 306 | --values $(pwd)/platform.yaml \ 307 | ${VALUES_STR} \ 308 | ${{ inputs.helm-args }} \ 309 | ${{ steps.arguments.outputs.kube_version }} \ 310 | > ${{ steps.config.outputs.tmp }}/manifests/resources.yaml 311 | env: 312 | IMAGE_NAME: ${{ inputs.image }} 313 | IMAGE_TAG: ${{ inputs.image-tag }} 314 | 315 | - name: Get Webapp 316 | if: ${{ inputs.operation == 'deploy' }} 317 | id: result 318 | shell: bash 319 | run: |- 320 | WEBAPP_URL=$( \ 321 | yq -N eval-all '[.metadata.annotations["outputs.platform.cloudposse.com/webapp-url"] | select(. != null)] | .[0]' \ 322 | ${{ steps.config.outputs.tmp }}/manifests/resources.yaml \ 323 | ) 324 | echo "webapp_url=${WEBAPP_URL}" >> $GITHUB_OUTPUT 325 | 326 | - name: Deplicated Ref 327 | if: ${{ inputs.operation == 'deploy' }} 328 | id: ref 329 | uses: cloudposse/github-action-yaml-config-query@0.1.3 330 | with: 331 | query: .${{ inputs.gitref-sha == '' }} 332 | config: |- 333 | true: 334 | value: ${{ inputs.ref }} 335 | false: 336 | value: ${{ inputs.gitref-sha }} 337 | 338 | - name: Config render 339 | if: ${{ inputs.operation == 'deploy' }} 340 | uses: 1arp/create-a-file-action@0.2 341 | with: 342 | path: ${{ steps.config.outputs.tmp }} 343 | file: config.yaml 344 | content: |- 345 | app_repository: ${{ inputs.repository }} 346 | app_commit: ${{ steps.ref.outputs.value }} 347 | app_hostname: ${{ steps.result.outputs.webapp_url }} 348 | name: ${{ inputs.namespace }}.${{ inputs.application }} 349 | namespace: ${{ inputs.namespace }} 350 | manifests: ${{ steps.config.outputs.path }}/manifests 351 | 352 | - name: Push to Github 353 | uses: nick-fields/retry@v2 354 | id: git 355 | with: 356 | max_attempts: ${{ inputs.commit-retry-count }} 357 | timeout_seconds: ${{ inputs.commit-timeout }} 358 | retry_wait_seconds: ${{ inputs.commit-retry-interval }} 359 | shell: bash 360 | command: |- 361 | set -e 362 | 363 | git config --global user.email "bot@example.com" 364 | git config --global user.name "cloudpossebot" 365 | 366 | pushd ./${{ steps.destination_dir.outputs.name }} 367 | 368 | git reset --hard origin/${{ steps.destination.outputs.ref }} 369 | git pull --rebase 370 | 371 | popd 372 | 373 | case '${{ inputs.operation }}' in 374 | 375 | deploy) 376 | cp -r ./tmp/* ./${{ steps.destination_dir.outputs.name }}/ 377 | ;; 378 | 379 | destroy) 380 | rm -rf ./${{ steps.destination_dir.outputs.name }}/${{ steps.config.outputs.path }} 381 | ;; 382 | 383 | *) 384 | echo "Operation should be `deploy` or `destroy`" 385 | exit 1; 386 | ;; 387 | esac 388 | 389 | pushd ./${{ steps.destination_dir.outputs.name }} 390 | 391 | git add -A 392 | git status 393 | git diff-index --quiet HEAD || git commit -m "Deploy ${{ github.repository }} SHA ${{ github.sha }} RUN ${{ github.run_id }} ATEMPT ${{ github.run_attempt }}" 394 | git push origin ${{ steps.destination.outputs.ref }} 395 | 396 | echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 397 | 398 | popd 399 | 400 | - name: Select GitHub Token for Sync Mode 401 | id: commit_status_github_token 402 | if: ${{ inputs.synchronously == 'true' && inputs.operation == 'deploy' }} 403 | shell: bash 404 | run: |- 405 | if [ -z "${{ inputs.commit-status-github-token }}" ]; then 406 | echo "token=${{ inputs.github-pat }}" >> $GITHUB_OUTPUT 407 | else 408 | echo "token=${{ inputs.commit-status-github-token }}" >> $GITHUB_OUTPUT 409 | fi 410 | 411 | - uses: cloudposse/github-action-wait-commit-status@0.2.0 412 | if: ${{ inputs.synchronously == 'true' && inputs.operation == 'deploy' }} 413 | with: 414 | repository: ${{ inputs.repository }} 415 | sha: ${{ inputs.ref }} 416 | status: "continuous-delivery/${{ inputs.namespace }}.${{ inputs.application }}" 417 | expected_state: "success" 418 | token: ${{ steps.commit_status_github_token.outputs.token }} 419 | check-retry-count: ${{ inputs.check-retry-count }} 420 | check-retry-interval: ${{ inputs.check-retry-interval }} 421 | --------------------------------------------------------------------------------