├── .github ├── PULL_REQUEST_TEMPLATE.md ├── release-drafter.yaml └── workflows │ ├── create-release.yaml │ └── validate-pr-title.yaml ├── .gitignore ├── Dockerfile ├── README.md ├── cf-deploy-kubernetes.sh ├── codefresh.yml ├── service.yaml └── template.sh /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What 2 | 3 | ## Why 4 | 5 | ## Notes 6 | 7 | 8 | ## Labels 9 | 10 | Assign the following labels to the PR: 11 | 12 | `security` - to trigger image scanning in CI build 13 | 14 | ## PR Comments 15 | 16 | Add the following comments to the PR: 17 | 18 | `/e2e` - to trigger E2E build 19 | -------------------------------------------------------------------------------- /.github/release-drafter.yaml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION' 2 | tag-template: 'v$RESOLVED_VERSION' 3 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 4 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 5 | template: | 6 | ## Changes 7 | 8 | $CHANGES -------------------------------------------------------------------------------- /.github/workflows/create-release.yaml: -------------------------------------------------------------------------------- 1 | ## Reference: https://github.com/release-drafter/release-drafter 2 | name: Create Release 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | create_release: 11 | name: Create Release 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | pull-requests: write 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Set up YQ 23 | uses: frenck/action-setup-yq@v1 24 | 25 | - name: Get release version from service.yaml 26 | run: | 27 | RELEASE_VERSION=$(yq eval '.version' service.yaml ) 28 | echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV 29 | 30 | - uses: release-drafter/release-drafter@v5 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | with: 34 | publish: true 35 | version: ${{ env.RELEASE_VERSION }} 36 | config-name: release-drafter.yaml 37 | -------------------------------------------------------------------------------- /.github/workflows/validate-pr-title.yaml: -------------------------------------------------------------------------------- 1 | ## Reference: https://github.com/amannn/action-semantic-pull-request 2 | name: PR title 3 | 4 | on: 5 | pull_request: 6 | types: 7 | - opened 8 | - reopened 9 | - edited 10 | - synchronize 11 | 12 | jobs: 13 | validate-pr-title: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | pull-requests: read 17 | statuses: write 18 | steps: 19 | - uses: amannn/action-semantic-pull-request@v5.4.0 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | with: 23 | requireScope: false 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.21 AS builder 2 | 3 | RUN apk add --no-cache curl 4 | 5 | ARG TARGETARCH 6 | WORKDIR /tmp/kubectl-versions 7 | RUN curl -o kubectl1.6 -L https://storage.googleapis.com/kubernetes-release/release/v1.6.0/bin/linux/${TARGETARCH}/kubectl 8 | RUN curl -o kubectl1.10 -L https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/${TARGETARCH}/kubectl 9 | RUN curl -o kubectl1.11 -L https://storage.googleapis.com/kubernetes-release/release/v1.11.0/bin/linux/${TARGETARCH}/kubectl 10 | RUN curl -o kubectl1.12 -L https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/${TARGETARCH}/kubectl 11 | RUN curl -o kubectl1.13 -L https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/${TARGETARCH}/kubectl 12 | RUN curl -o kubectl1.14 -L https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/linux/${TARGETARCH}/kubectl 13 | RUN curl -o kubectl1.15 -L https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/${TARGETARCH}/kubectl 14 | RUN curl -o kubectl1.16 -L https://storage.googleapis.com/kubernetes-release/release/v1.16.0/bin/linux/${TARGETARCH}/kubectl 15 | RUN curl -o kubectl1.17 -L https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/${TARGETARCH}/kubectl 16 | RUN curl -o kubectl1.18 -L https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/${TARGETARCH}/kubectl 17 | RUN curl -o kubectl1.19 -L https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/${TARGETARCH}/kubectl 18 | RUN curl -o kubectl1.20 -L https://storage.googleapis.com/kubernetes-release/release/v1.20.0/bin/linux/${TARGETARCH}/kubectl 19 | RUN curl -o kubectl1.21 -L https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/${TARGETARCH}/kubectl 20 | RUN curl -o kubectl1.22 -L https://storage.googleapis.com/kubernetes-release/release/v1.22.0/bin/linux/${TARGETARCH}/kubectl 21 | RUN curl -o kubectl1.23 -L https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/linux/${TARGETARCH}/kubectl 22 | RUN curl -o kubectl1.24 -L https://storage.googleapis.com/kubernetes-release/release/v1.24.0/bin/linux/${TARGETARCH}/kubectl 23 | RUN curl -o kubectl1.25 -L https://storage.googleapis.com/kubernetes-release/release/v1.25.0/bin/linux/${TARGETARCH}/kubectl 24 | RUN curl -o kubectl1.26 -L https://storage.googleapis.com/kubernetes-release/release/v1.26.0/bin/linux/${TARGETARCH}/kubectl 25 | RUN curl -o kubectl1.27 -L https://storage.googleapis.com/kubernetes-release/release/v1.27.0/bin/linux/${TARGETARCH}/kubectl 26 | RUN curl -o kubectl1.28 -L https://storage.googleapis.com/kubernetes-release/release/v1.28.0/bin/linux/${TARGETARCH}/kubectl 27 | RUN curl -o kubectl1.29 -L https://storage.googleapis.com/kubernetes-release/release/v1.29.0/bin/linux/${TARGETARCH}/kubectl 28 | RUN curl -o kubectl1.30 -L https://storage.googleapis.com/kubernetes-release/release/v1.30.0/bin/linux/${TARGETARCH}/kubectl 29 | RUN curl -o kubectl1.31 -L https://storage.googleapis.com/kubernetes-release/release/v1.31.0/bin/linux/${TARGETARCH}/kubectl 30 | 31 | FROM debian:bookworm-20250407-slim 32 | WORKDIR / 33 | RUN adduser --gecos "" --disabled-password --home /home/cfu --shell /bin/bash cfu 34 | USER cfu 35 | 36 | # copy all versions of kubectl to switch between them later. 37 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.6 /usr/local/bin/ 38 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.10 /usr/local/bin/kubectl 39 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.11 /usr/local/bin/ 40 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.12 /usr/local/bin/ 41 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.13 /usr/local/bin/ 42 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.14 /usr/local/bin/ 43 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.15 /usr/local/bin/ 44 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.16 /usr/local/bin/ 45 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.17 /usr/local/bin/ 46 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.18 /usr/local/bin/ 47 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.19 /usr/local/bin/ 48 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.20 /usr/local/bin/ 49 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.21 /usr/local/bin/ 50 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.22 /usr/local/bin/ 51 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.23 /usr/local/bin/ 52 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.24 /usr/local/bin/ 53 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.25 /usr/local/bin/ 54 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.26 /usr/local/bin/ 55 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.27 /usr/local/bin/ 56 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.28 /usr/local/bin/ 57 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.29 /usr/local/bin/ 58 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.30 /usr/local/bin/ 59 | COPY --chown=cfu --chmod=775 --from=builder /tmp/kubectl-versions/kubectl1.31 /usr/local/bin/ 60 | 61 | COPY --chown=cfu --chmod=775 cf-deploy-kubernetes.sh /cf-deploy-kubernetes 62 | COPY --chown=cfu --chmod=775 template.sh /template.sh 63 | 64 | CMD ["bash"] 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Abstract 2 | 3 | This is the source code for the `codefresh/cf-deploy-kubernetes` container. 4 | This container is used to demonstrate a Kubernetes deployment using Codefresh.io 5 | 6 | # Assumptions 7 | 8 | The deployment script makes the following assumptions about your application and 9 | Kubernetes configuration: 10 | 11 | 1. The application is deployed using the Kubernetes deployment API (versus the 12 | the replication controller directly). For more information read 13 | http://kubernetes.io/docs/user-guide/deployments/ 14 | 2. The tested codebase has a yaml file (i.e. deployment.yml) that describes the Kubernetes deployment 15 | parameters and configuration of your application. 16 | 3. The script processes deployment.yml as a simple template where all `{{ ENV_VARIABLE }}` are replaced with a value of $ENV_VARIABLE deployment.yml 17 | 18 | # Configuration 19 | 20 | The following env variables control the deployment configuration: 21 | 22 | 1. KUBERNETES_DEPLOYMENT_TIMEOUT - How much to wait for a successful deployment before failing the build. Defaults to 120 (secs). 23 | 2. KUBECONTEXT - corresponds to the name of a cluster added to codefresh 24 | 3. KUBERNETES_NAMESPACE - The namespace to deploy 25 | 4. KUBECTL_ACTION - means an action for `kubectl `. Valid values are apply|create|replace. Default is "apply" 26 | 27 | Optional: 28 | 29 | `SERVER_VERSION` - Manually set the Minor kubectl version. Supports 10-22. 30 | 31 | # Usage in codefresh.io 32 | 33 | ### deployment.yml 34 | 35 | ```yaml 36 | --- 37 | apiVersion: extensions/v1beta1 38 | kind: Deployment 39 | metadata: 40 | name: api-svc 41 | spec: 42 | replicas: 1 43 | template: 44 | metadata: 45 | annotations: 46 | revision: "{{CF_REVISION}}" 47 | labels: 48 | app: api-svc 49 | spec: 50 | containers: 51 | - name: apisvc 52 | image: myrepo/apisvc:{{CF_BRANCH}}-{{CF_REVISION}} 53 | ports: 54 | - containerPort: 80 55 | name: http 56 | 57 | ``` 58 | 59 | ### codefresh.yml 60 | ```yaml 61 | --- 62 | version: '1.0' 63 | 64 | steps: 65 | build: 66 | type: build 67 | dockerfile: Dockerfile 68 | image_name: myrepo/apisvc 69 | tag: '${{CF_BRANCH}}-{{CF_REVISION}}' 70 | 71 | push: 72 | type: push 73 | candidate: ${{build}} 74 | tag: '${{CF_BRANCH}}-{{CF_REVISION}}' 75 | 76 | deploy-to-kubernetes: 77 | image: codefresh/cf-deploy-kubernetes 78 | tag: latest 79 | working_directory: ${{clone}} 80 | commands: 81 | - /cf-deploy-kubernetes deployment.yml 82 | environment: 83 | - KUBECONTEXT=my-clusterg@my-staging 84 | - KUBERNETES_NAMESPACE=mynamespace 85 | ``` 86 | -------------------------------------------------------------------------------- /cf-deploy-kubernetes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | fatal() { 4 | echo "ERROR: $1" 5 | exit 1 6 | } 7 | 8 | readonly KUBECTL_ACTION=${KUBECTL_ACTION:-apply} 9 | [[ $KUBECTL_ACTION =~ ^(apply|create|replace)$ ]] || fatal "KUBECTL_ACTION should be one of apply|create|replace " 10 | 11 | deployment_file=${1:-deployment.yml} 12 | : ${KUBERNETES_NAMESPACE:=default} 13 | : ${KUBERNETES_DEPLOYMENT_TIMEOUT:=120} 14 | 15 | 16 | if [[ -n "$KUBERNETES_SERVER" && -n "$KUBERNETES_USER" && -n "$KUBERNETES_PASSWORD" ]]; then 17 | unset KUBECONFIG 18 | 19 | echo "---> Setting up Kubernetes credentials..." 20 | kubectl config set-credentials deployer --username=$KUBERNETES_USER --password=$KUBERNETES_PASSWORD 21 | kubectl config set-cluster foo.kubernetes.com --insecure-skip-tls-verify=true --server=$KUBERNETES_SERVER 22 | kubectl config set-context foo.kubernetes.com/deployer --user=deployer --namespace=$KUBERNETES_NAMESPACE --cluster=foo.kubernetes.com 23 | kubectl config use-context foo.kubernetes.com/deployer 24 | 25 | KUBECONTEXT=foo.kubernetes.com/deployer 26 | else 27 | if [[ -z "${KUBECONTEXT}" ]]; then 28 | KUBECONTEXT=$(kubectl config current-context) 29 | # If KUBECONFIG is set we obligate to set KUBECONTEXT to valid context name 30 | if [[ -n "${KUBECONFIG}" ]]; then 31 | echo -e "--- ERROR - KUBECONTEXT Environment variable is not set, please set it to one of integrated contexts: " 32 | kubectl config get-contexts 33 | fatal "KUBECONTEXT is not set " 34 | else 35 | KUBECONTEXT=$(kubectl config current-context) 36 | fi 37 | fi 38 | fi 39 | 40 | # Add SERVER_VERSION override and testing capabilities 41 | 42 | if [[ -n "${SERVER_VERSION}" ]]; then 43 | # Statically define SERVER_VERSION from variable override 44 | echo "Statically defined version: ${SERVER_VERSION}" 45 | # Assign kubectl version 46 | echo "Setting kubectl to version 1.${SERVER_VERSION}" 47 | cp -f "/usr/local/bin/kubectl1.${SERVER_VERSION}" /usr/local/bin/kubectl 2>/dev/null 48 | else 49 | #check the cluster version and decide which version of kubectl to use: 50 | SERVER_VERSION=$(kubectl version --short=true --context "${KUBECONTEXT}" | grep -i server | cut -d ':' -f2 | cut -d '.' -f2 | sed 's/[^0-9]*//g') 51 | echo "Server minor version: $SERVER_VERSION" 52 | if (( "$SERVER_VERSION" <= "6" )); then cp -f /usr/local/bin/kubectl1.6 /usr/local/bin/kubectl; fi 2>/dev/null 53 | if (( "$SERVER_VERSION" <= "7" )); then cp -f /usr/local/bin/kubectl1.7 /usr/local/bin/kubectl; fi 2>/dev/null 54 | if (( "$SERVER_VERSION" <= "8" )); then cp -f /usr/local/bin/kubectl1.8 /usr/local/bin/kubectl; fi 2>/dev/null 55 | if (( "$SERVER_VERSION" <= "9" )); then cp -f /usr/local/bin/kubectl1.9 /usr/local/bin/kubectl; fi 2>/dev/null 56 | if (( "$SERVER_VERSION" <= "10" )); then cp -f /usr/local/bin/kubectl1.10 /usr/local/bin/kubectl; fi 2>/dev/null 57 | if (( "$SERVER_VERSION" <= "11" )); then cp -f /usr/local/bin/kubectl1.11 /usr/local/bin/kubectl; fi 2>/dev/null 58 | if (( "$SERVER_VERSION" <= "12" )); then cp -f /usr/local/bin/kubectl1.12 /usr/local/bin/kubectl; fi 2>/dev/null 59 | if (( "$SERVER_VERSION" <= "13" )); then cp -f /usr/local/bin/kubectl1.13 /usr/local/bin/kubectl; fi 2>/dev/null 60 | if (( "$SERVER_VERSION" == "14" )); then cp -f /usr/local/bin/kubectl1.14 /usr/local/bin/kubectl; fi 2>/dev/null 61 | if (( "$SERVER_VERSION" == "15" )); then cp -f /usr/local/bin/kubectl1.15 /usr/local/bin/kubectl; fi 2>/dev/null 62 | if (( "$SERVER_VERSION" == "16" )); then cp -f /usr/local/bin/kubectl1.16 /usr/local/bin/kubectl; fi 2>/dev/null 63 | if (( "$SERVER_VERSION" == "17" )); then cp -f /usr/local/bin/kubectl1.17 /usr/local/bin/kubectl; fi 2>/dev/null 64 | if (( "$SERVER_VERSION" == "18" )); then cp -f /usr/local/bin/kubectl1.18 /usr/local/bin/kubectl; fi 2>/dev/null 65 | if (( "$SERVER_VERSION" == "19" )); then cp -f /usr/local/bin/kubectl1.19 /usr/local/bin/kubectl; fi 2>/dev/null 66 | if (( "$SERVER_VERSION" == "20" )); then cp -f /usr/local/bin/kubectl1.20 /usr/local/bin/kubectl; fi 2>/dev/null 67 | if (( "$SERVER_VERSION" == "21" )); then cp -f /usr/local/bin/kubectl1.21 /usr/local/bin/kubectl; fi 2>/dev/null 68 | if (( "$SERVER_VERSION" == "22" )); then cp -f /usr/local/bin/kubectl1.22 /usr/local/bin/kubectl; fi 2>/dev/null 69 | if (( "$SERVER_VERSION" == "23" )); then cp -f /usr/local/bin/kubectl1.23 /usr/local/bin/kubectl; fi 2>/dev/null 70 | if (( "$SERVER_VERSION" >= "24" )); then cp -f /usr/local/bin/kubectl1.24 /usr/local/bin/kubectl; fi 2>/dev/null 71 | if (( "$SERVER_VERSION" >= "25" )); then cp -f /usr/local/bin/kubectl1.25 /usr/local/bin/kubectl; fi 2>/dev/null 72 | if (( "$SERVER_VERSION" >= "26" )); then cp -f /usr/local/bin/kubectl1.26 /usr/local/bin/kubectl; fi 2>/dev/null 73 | if (( "$SERVER_VERSION" >= "27" )); then cp -f /usr/local/bin/kubectl1.27 /usr/local/bin/kubectl; fi 2>/dev/null 74 | if (( "$SERVER_VERSION" >= "28" )); then cp -f /usr/local/bin/kubectl1.28 /usr/local/bin/kubectl; fi 2>/dev/null 75 | if (( "$SERVER_VERSION" >= "29" )); then cp -f /usr/local/bin/kubectl1.29 /usr/local/bin/kubectl; fi 2>/dev/null 76 | if (( "$SERVER_VERSION" >= "30" )); then cp -f /usr/local/bin/kubectl1.30 /usr/local/bin/kubectl; fi 2>/dev/null 77 | if (( "$SERVER_VERSION" >= "31" )); then cp -f /usr/local/bin/kubectl1.31 /usr/local/bin/kubectl; fi 2>/dev/null 78 | [ ! -f "${deployment_file}" ] && echo "Couldn't find $deployment_file file at $(pwd)" && exit 1; 79 | fi 80 | 81 | # Simple testing logic for making sure override versions are set 82 | if [[ -n "${KUBE_CTL_TEST_VERSION}" ]]; then 83 | KUBE_CTL_VERSION=`kubectl version --client --short` 84 | echo "Testing kubectl version is set..." 85 | if [[ "${KUBE_CTL_VERSION}" == *"${KUBE_CTL_TEST_VERSION}"* ]]; then 86 | echo "Version correctly set" 87 | echo "Kubectl Version: ${KUBE_CTL_VERSION}" 88 | echo "Test Version: ${KUBE_CTL_TEST_VERSION}" 89 | exit 0 90 | else 91 | echo "Kubectl Version: ${KUBE_CTL_VERSION}" 92 | echo "Test Version: ${KUBE_CTL_TEST_VERSION}" 93 | fatal "Version Mismatch!!!" 94 | exit 1 95 | fi 96 | fi 97 | 98 | DEPLOYMENT_FILE=${deployment_file}-$(date '+%y-%m-%d_%H-%M-%S').yml 99 | $(dirname $0)/template.sh "$deployment_file" > "$DEPLOYMENT_FILE" || fatal "Failed to apply deployment template on $deployment_file" 100 | 101 | if (( "$SERVER_VERSION" <= "17" )); then 102 | dry_run_value=true 103 | else 104 | dry_run_value=client 105 | fi 106 | 107 | echo -e "\n\n---> Kubernetes objects to deploy in $deployment_file :" 108 | KUBECTL_OBJECTS=/tmp/deployment.objects 109 | kubectl $KUBECTL_ACTION \ 110 | --context "${KUBECONTEXT}" \ 111 | --namespace "${KUBERNETES_NAMESPACE}" \ 112 | --dry-run=${dry_run_value} \ 113 | -f "$DEPLOYMENT_FILE" \ 114 | -o go-template \ 115 | --template '{{ if .items }}{{ range .items }}{{ printf "%-30s%-50s\n" .kind .metadata.name}}{{end}}{{else}}{{ printf "%-30s%-50s\n" .kind .metadata.name}}{{end}}' \ 116 | > >(tee $KUBECTL_OBJECTS) 2>${KUBECTL_OBJECTS}.errors 117 | 118 | if [ $? != 0 ]; then 119 | echo -e "\nERROR Failed to parse ${deployment_file}" 120 | cat ${KUBECTL_OBJECTS}.errors 121 | fi 122 | 123 | DEPLOYMENT_NAME=$(awk '/^Deployment /{a=$2}END{print a}' $KUBECTL_OBJECTS) 124 | 125 | echo -e "\n\n---> Submitting a deployment to Kubernetes by 126 | kubectl --context "${KUBECONTEXT}" --namespace "${KUBERNETES_NAMESPACE}" $KUBECTL_ACTION " 127 | kubectl --context "${KUBECONTEXT}" --namespace "${KUBERNETES_NAMESPACE}" $KUBECTL_ACTION -f "$DEPLOYMENT_FILE" || fatal "Deployment submitting Failed" 128 | 129 | if [ -n "$DEPLOYMENT_NAME" ]; then 130 | echo "---> Waiting for a successful deployment/${DEPLOYMENT_NAME} status to namespace ${KUBERNETES_NAMESPACE} ..." 131 | timeout -s SIGTERM $KUBERNETES_DEPLOYMENT_TIMEOUT kubectl --context "${KUBECONTEXT}" --namespace "${KUBERNETES_NAMESPACE}" rollout status deployment/"${DEPLOYMENT_NAME}" || fatal "Deployment Failed" 132 | fi 133 | -------------------------------------------------------------------------------- /codefresh.yml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | stages: 3 | - clone 4 | - prepare 5 | - build 6 | - release 7 | steps: 8 | 9 | main_clone: 10 | title: 'Cloning main repository...' 11 | stage: clone 12 | type: git-clone 13 | repo: ${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} 14 | revision: ${{CF_BRANCH}} 15 | git: ${{GIT_CONTEXT}} 16 | 17 | prepare_env_vars: 18 | title: 'Preparing environment variables...' 19 | stage: prepare 20 | image: codefreshio/ci-helpers 21 | working_directory: ${{main_clone}} 22 | commands: 23 | - cf_export SERVICE_VERSION=$(yq r service.yaml version) 24 | - cf_export IMAGE_NAME=codefresh/cf-deploy-kubernetes 25 | 26 | validate_version: 27 | title: 'Validating the service version...' 28 | stage: prepare 29 | image: codefreshio/ci-helpers 30 | fail_fast: false 31 | commands: 32 | - | 33 | err() { echo -e "\e[31m$@\e[0m" ; return 1 ; } 34 | ok() { echo -e "\e[32m$@\e[0m" ; return 0 ; } 35 | 36 | current_version=${SERVICE_VERSION} 37 | last_version=$(git describe --abbrev=0 --tags) 38 | echo "Current version is $current_version, last version - $last_version" 39 | semver-cli greater $current_version $last_version && ok "Version check ok" || err "Please the update the version in the service.yaml file" 40 | 41 | build_image: 42 | title: "Building the image..." 43 | stage: build 44 | type: build 45 | working_directory: ${{main_clone}} 46 | dockerfile: ./Dockerfile 47 | build_arguments: 48 | - COMPOSE_VERSION=${{COMPOSE_VERSION}} 49 | image_name: ${{IMAGE_NAME}} 50 | tag: ${{CF_BRANCH_TAG_NORMALIZED}} 51 | 52 | approve_existing_version_update: 53 | type: pending-approval 54 | stage: release 55 | title: "Are you sure you want to update already existing image version?" 56 | description: | 57 | "Used for reverting changes without raising the service version" 58 | when: 59 | branch: 60 | only: [master] 61 | steps: 62 | - name: validate_version 63 | on: 64 | - failure 65 | 66 | release: 67 | type: parallel 68 | stage: release 69 | steps: 70 | 71 | add_git_tag: 72 | title: "Adding Git tag..." 73 | stage: release 74 | image: codefreshio/ci-helpers 75 | commands: 76 | - source /get-token/get-gh-token.sh 77 | - | 78 | curl --fail -X POST -d '{"ref": "refs/tags/${{SERVICE_VERSION}}","sha": "${{CF_REVISION}}"}' -H "Content-Type: application/json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}/git/refs 79 | when: 80 | branch: 81 | only: [master] 82 | steps: 83 | - name: validate_version 84 | on: 85 | - success 86 | 87 | push_image_prod: 88 | type: push 89 | title: "Pushing the image to the public registry..." 90 | stage: release 91 | image_name: '${{IMAGE_NAME}}' 92 | registry: "${{REGISTRY_INTEGRATION}}" 93 | candidate: "${{build_image}}" 94 | tags: 95 | - "${{SERVICE_VERSION}}" 96 | - "latest" 97 | when: 98 | branch: 99 | only: [master] -------------------------------------------------------------------------------- /service.yaml: -------------------------------------------------------------------------------- 1 | version: 16.2.8 2 | -------------------------------------------------------------------------------- /template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Very simple templating system that replaces {{VAR}} by the value of $VAR. 4 | # Supports default values by writting {{VAR=value}} in the template. 5 | # 6 | # Copyright (c) 2017 Sébastien Lavoie 7 | # Copyright (c) 2017 Johan Haleby 8 | # 9 | # By: https://github.com/johanhaleby/bash-templater 10 | # Version: https://github.com/johanhaleby/bash-templater/commit/5ac655d554238ac70b08ee4361d699ea9954c941 11 | 12 | # Replaces all {{VAR}} by the $VAR value in a template file and outputs it 13 | 14 | readonly PROGNAME=$(basename $0) 15 | 16 | config_file="" 17 | print_only="false" 18 | silent="false" 19 | 20 | usage="${PROGNAME} [-h] [-d] [-f] [-s] -- 21 | where: 22 | -h, --help 23 | Show this help text 24 | -p, --print-envs 25 | Don't do anything, just print the result of the variable expansion(s) 26 | -e, --env-file 27 | Specify a file to read variables from 28 | -s, --silent 29 | Don't print warning messages (for example if no variables are found) 30 | examples: 31 | VAR1=Something VAR2=1.2.3 ${PROGNAME} test.txt 32 | ${PROGNAME} test.txt -e my-variables.txt 33 | ${PROGNAME} test.txt -e my-variables.txt > new-test.txt" 34 | 35 | if [ $# -eq 0 ]; then 36 | echo "$usage" 37 | exit 1 38 | fi 39 | 40 | while [[ $1 =~ ^(-(h|p|e|s)|--(help|print-envs|env-file|silent)) ]] 41 | do 42 | key=$1 43 | value=$2 44 | 45 | case $key in 46 | -h|--help) 47 | echo "$usage" 48 | exit 0 49 | ;; 50 | -p|--print) 51 | print_only="true" 52 | ;; 53 | -e|--env-file) 54 | config_file="$2" 55 | shift 56 | ;; 57 | -s|--silent) 58 | silent="true" 59 | ;; 60 | *) 61 | echo "Usage ERROR: Invalid Option $key" 62 | echo "$usage" 63 | exit 1 64 | ;; 65 | esac 66 | shift # past argument or value 67 | done 68 | 69 | 70 | if [[ ! -f "${1}" ]]; then 71 | echo "You need to specify a template file" >&2 72 | echo "$usage" 73 | exit 1 74 | fi 75 | 76 | template="${1}" 77 | 78 | if [ "$#" -ne 0 ]; then 79 | while [ "$#" -gt 0 ] 80 | do 81 | case "$1" in 82 | -h|--help) 83 | echo "$usage" 84 | exit 0 85 | ;; 86 | -p|--print-envs) 87 | print_only="true" 88 | ;; 89 | -f|--file) 90 | config_file="$2" 91 | ;; 92 | -s|--silent) 93 | silent="true" 94 | ;; 95 | --) 96 | break 97 | ;; 98 | -*) 99 | echo "Invalid option '$1'. Use --help to see the valid options" >&2 100 | exit 1 101 | ;; 102 | # an option argument, continue 103 | *) ;; 104 | esac 105 | shift 106 | done 107 | fi 108 | 109 | vars=$(grep -oE '\{\{[A-Za-z0-9_]+\}\}' "${template}" | sort | uniq | sed -e 's/^{{//' -e 's/}}$//') 110 | 111 | if [[ -z "$vars" ]]; then 112 | if [ "$silent" == "false" ]; then 113 | echo "Warning: No variable was found in ${template}, syntax is {{VAR}}" >&2 114 | fi 115 | cat ${template} 116 | exit 0 117 | fi 118 | 119 | # Load variables from file if needed 120 | if [ "${config_file}" != "" ]; then 121 | if [[ ! -f "${config_file}" ]]; then 122 | echo "The file ${config_file} does not exists" >&2 123 | echo "$usage" 124 | exit 1 125 | fi 126 | 127 | # Create temp file where & and "space" is escaped 128 | tmpfile=`mktemp` 129 | sed -e "s;\&;\\\&;g" -e "s;\ ;\\\ ;g" "${config_file}" > $tmpfile 130 | source $tmpfile 131 | fi 132 | 133 | var_value() { 134 | eval echo \$$1 135 | } 136 | 137 | replaces="" 138 | 139 | # Reads default values defined as {{VAR=value}} and delete those lines 140 | # There are evaluated, so you can do {{PATH=$HOME}} or {{PATH=`pwd`}} 141 | # You can even reference variables defined in the template before 142 | defaults=$(grep -oE '^\{\{[A-Za-z0-9_]+=.+\}\}' "${template}" | sed -e 's/^{{//' -e 's/}}$//') 143 | 144 | for default in $defaults; do 145 | var=$(echo "$default" | grep -oE "^[A-Za-z0-9_]+") 146 | current=`var_value $var` 147 | 148 | # Replace only if var is not set 149 | if [[ -z "$current" ]]; then 150 | eval $default 151 | fi 152 | 153 | # remove define line 154 | replaces="-e '/^{{$var=/d' $replaces" 155 | vars="$vars 156 | $current" 157 | done 158 | 159 | vars=$(echo $vars | sort | uniq) 160 | 161 | if [[ "$print_only" == "true" ]]; then 162 | for var in $vars; do 163 | value=`var_value $var` 164 | echo "$var = $value" 165 | done 166 | exit 0 167 | fi 168 | 169 | # Replace all {{VAR}} by $VAR value 170 | for var in $vars; do 171 | value=`var_value $var` 172 | if [[ -z "$value" ]]; then 173 | if [ $silent == "false" ]; then 174 | echo "Warning: $var is not defined and no default is set, replacing by empty" >&2 175 | fi 176 | fi 177 | 178 | # Escape slashes 179 | value=$(echo "$value" | sed 's/\//\\\//g'); 180 | replaces="-e 's/{{$var}}/${value}/g' $replaces" 181 | done 182 | 183 | escaped_template_path=$(echo $template | sed 's/ /\\ /g') 184 | eval sed $replaces "$escaped_template_path" 185 | --------------------------------------------------------------------------------