diff --git a/.circleci/config.yml b/.circleci/config.yml index 8a00ce7723..a8fca70266 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,1224 +1,19 @@ -# CircleCI 2.1 configuration file version: 2.1 -orbs: - win: circleci/windows@2.2.0 - rok8s-scripts: fairwinds/rok8s-scripts@11.1.3 - -# Shared config to use between jobs -# These can be used to inject shared variables -# see https://blog.daemonl.com/2016/02/yaml.html -.references: - shared-env-config: &shared-env-config - GARDEN_DISABLE_VERSION_CHECK: "true" - GARDEN_DISABLE_ANALYTICS: "true" - GARDEN_K8S_BUILD_SYNC_MODE: "mutagen" - - shared-machine-config: &shared-machine-config - image: "ubuntu-2204:2023.02.1" - docker_layer_caching: true - - remote-docker: &remote-docker - setup_remote_docker: - version: 20.10.24 - docker_layer_caching: true - - runner-image: &runner-image - image: gardendev/circleci-runner:18.15.0-1@sha256:c830e29ab30a1c5b08cba4d041d3325ef6958aebeba1b10b1ee9566d7b1a4d42 - - # Configuration for our node jobs - node-config: &node-config - docker: - - <<: *runner-image - environment: - <<: *shared-env-config - resource_class: medium - - # Configuration for release jobs - release-config: &release-config - docker: - - <<: *runner-image - - # Attaches the current saved workspace - attach-workspace: &attach-workspace - attach_workspace: - at: ./ - - only-prs: &only-prs - filters: - branches: - ignore: main - tags: - ignore: /.*/ - - # Only run jobs on main branch - only-main: &only-main - filters: - branches: - only: - - main - tags: - ignore: /.*/ - - # Only run on versioned tags - only-tags: &only-tags - filters: - branches: - ignore: /.*/ - tags: - only: /\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?/ - - # Only run for PRs from core team - only-internal-prs: &only-internal-prs - filters: - branches: - # Forked pull requests have CIRCLE_BRANCH set to pull/XXX - ignore: /pull\/[0-9]+/ - -# Reuseable commands to execute in jobs -# see https://circleci.com/docs/2.0/configuration-reference/#commands-requires-version21 -# and example https://github.com/mapbox/mapbox-gl-native/blob/master/circle.yml -commands: - npm_install: - description: | - Installs npm packages and loads and saves the caches as appropriate - parameters: - context: - description: Set this to vm if installing in a VM, to avoid conflicting caches with the docker runs - type: string - default: docker - steps: - - restore_cache: - keys: - - npm-v2-<>-{{ checksum "package-lock.json" }} - - - run: npm ci - - - save_cache: - key: npm-v2-<>-{{ checksum "package-lock.json" }} - paths: - - node_modules - - cli/node_modules - - core/node_modules - - e2e/node_modules - - plugins/conftest/node_modules - - plugins/conftest-container/node_modules - - plugins/conftest-kubernetes/node_modules - - plugins/jib/node_modules - - plugins/maven-container/node_modules - - plugins/pulumi/node_modules - - plugins/terraform/node_modules - - sdk/node_modules - - configure_git: - description: Configure git (needed for some tests) - steps: - - run: - name: Configure git - # ensure that file transfer protocol is allowed, see https://vielmetti.typepad.com/logbook/2022/10/git-security-fixes-lead-to-fatal-transport-file-not-allowed-error-in-ci-systems-cve-2022-39253.html - command: | - git config --global user.name "Garden CI" - git config --global user.email "admin@garden.io" - git config --global protocol.file.allow "always" - - install_kubectl: - description: Install kubectl - steps: - - run: - name: Install binary dependencies - command: | - mkdir -p $HOME/bin - cd $HOME/bin - curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/amd64/kubectl - chmod +x kubectl - echo 'export PATH=$HOME/bin:$PATH' >> $BASH_ENV - - docker_login: - description: Login to Docker Hub - steps: - - run: - name: docker login - command: | - if [ -n "$DOCKER_PASS" ]; then - echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin - else - echo "Skipping, no login available" - fi - - install_kind: - description: Install Kind - parameters: - kindNodeImage: - description: The kind node image to use - type: string - steps: - - run: - name: Install kind - command: | - curl -LO https://github.com/kubernetes-sigs/kind/releases/download/v0.18.0/kind-linux-amd64 - chmod +x kind-linux-amd64 - sudo mv kind-linux-amd64 /usr/local/bin/kind - - run: - name: Start kind cluster - command: | - # Create the kind cluster with a custom config to enable the default ingress controller - cat \<> \ - --wait=600s \ - --config=- - - kind: Cluster - apiVersion: kind.x-k8s.io/v1alpha4 - nodes: - - role: control-plane - kubeadmConfigPatches: - - | - kind: InitConfiguration - nodeRegistration: - kubeletExtraArgs: - node-labels: "ingress-ready=true" - authorization-mode: "AlwaysAllow" - extraPortMappings: - - containerPort: 80 - hostPort: 80 - protocol: TCP - - containerPort: 443 - hostPort: 443 - protocol: TCP - EOF - - kubectl config set-context kind-kind - - configure_remote_cluster: - description: Configure the kubectl context via gcloud so that we can access our remote cluster. Used for e2e testing. - steps: - - run: - name: Configure kubectl context via gcloud and authenticate to Google Container Registry - command: | - export USE_GKE_GCLOUD_AUTH_PLUGIN=True - echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> $BASH_ENV - export GOOGLE_APPLICATION_CREDENTIALS=$HOME/gcloud-key.json - echo "export GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_APPLICATION_CREDENTIALS" >> $BASH_ENV - echo $GCLOUD_SERVICE_KEY > $GOOGLE_APPLICATION_CREDENTIALS - gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS - gcloud --quiet config set project $GOOGLE_PROJECT_ID - gcloud --quiet config set compute/zone $GOOGLE_COMPUTE_ZONE - gcloud --quiet container clusters get-credentials $GOOGLE_CLUSTER_ID --zone $GOOGLE_COMPUTE_ZONE - gcloud --quiet auth configure-docker - - cleanup_remote_cluster: - description: Clean up namespaces in the ci cluster on gcloud (to be used with configure_remote_cluster) - parameters: - filter: - description: What to grep namespaces by to select the current namespace to delete - type: string - steps: - - run: - name: Delete current namespace(s) - command: kubectl get ns | grep <> | awk '{print $1}' | xargs -n 1 kubectl delete namespace --wait=false || true - when: always - - run: - name: Delete namespaces older than 1 hour - # hack: find namespaces that contain '-ci' and their age ends with h or d, e.g. 1d5h or 24h - command: kubectl get ns | grep -E '(d|h)$' | grep -- '-testing' | awk '{print $1}' | xargs -n 1 kubectl delete namespace --wait=false || true - when: always - - build_dist: - description: Package built code into executables and persist to dist directory - parameters: - version: - description: | - The version tag used when building. Use to set the version string in the generated zip file names, - e.g. when creating unstable releases. The script defaults to using the version from core/package.json. - type: string - default: "" - steps: - # We need Docker for building the Alpine package - - *remote-docker - - checkout - - npm_install - - *attach-workspace - - restore_cache: - keys: - - pkg-v3-{{ checksum "package-lock.json" }} - - run: - name: Install Codesigning utility (needed for ARM64 on MacOS) - command: | - curl -Lo ldid https://github.com/ProcursusTeam/ldid/releases/download/v2.1.5-procursus7/ldid_linux_x86_64 - chmod +x ldid - sudo mv ldid /usr/local/bin - - run: - name: Setup buildx and qemu for cross-platform builds - command: | - sudo apt-get update - sudo apt-get install -y qemu-user-static - sudo apt-get install -y binfmt-support - - run: - name: Run dist script - command: npm run dist -- --version "<>" - - persist_to_workspace: - root: ./ - paths: - - dist/ - # Needed for the alpine docker build - - tmp/pkg/ - - save_cache: - key: pkg-v3-{{ checksum "package-lock.json" }} - paths: - - tmp/pkg-fetch - - run: - # No need to store the raw files as artifacts, we just want the archives - name: Cleanup - command: rm -rf dist/*-amd64 && rm -rf dist/*-arm64 - - store_artifacts: - path: dist - destination: dist - update_buildx: - description: Update buildx to a version that supports syntax in bakefile - steps: - - run: - name: Update buildx - command: | - mkdir -p ~/.docker/cli-plugins - wget -O ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.11.1/buildx-v0.11.1.linux-amd64 - echo "34927047282ef9052f57809fe94783b2dc0ab556fdd60c2c0b7f4e6e5f05a53b ${HOME}/.docker/cli-plugins/docker-buildx" | sha256sum -c - chmod +x ~/.docker/cli-plugins/docker-buildx - fail_fast: - description: Fail the whole workflow if this job fails in the merge queue - steps: - - run: - name: Fail Fast - when: on_fail - command: | - if [[ "${CIRCLE_BRANCH}" == "gh-readonly-queue"* ]]; then - echo "Canceling workflow as a step resulted in failure" - curl -X POST --header "Content-Type: application/json" "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}/cancel?circle-token=${CIRCLE_TOKEN}" - else - echo "Not canceling workflow as not running in merge queue" - fi - -# -# Jobs section -# -jobs: - build: - <<: *node-config - steps: - - checkout - - npm_install - - run: - name: build - command: | - npm run build - # Save the built output to be used for the docker image and for the release steps - - persist_to_workspace: - # Must be an absolute path, or relative path from working_directory. This is a directory on the container which is - # taken to be the root directory of the workspace. - root: ./ - # Must be relative path from root - paths: - # Save the built output for future - - cli/build/ - - core/build/ - - static/ - # TODO: see if we can make this somewhat more specific - - sdk/ - - plugins/ - - e2e/ - - fail_fast - - build-dist: - <<: *node-config - resource_class: xlarge - parameters: - version: - description: The version tag/name to set - type: string - default: "" - steps: - - build_dist: - version: <> - - fail_fast - - lint: - <<: *node-config - resource_class: large - steps: - - checkout - - npm_install - - *attach-workspace - - run: - name: lint - command: npm run lint - - fail_fast - - check-docs: - <<: *node-config - steps: - - checkout - - npm_install - - *attach-workspace - - run: - name: Make sure generated docs are up-to-date - command: npm run check-docs - - fail_fast - - check-package-licenses: - <<: *node-config - steps: - - checkout - - npm_install - - *attach-workspace - - run: - name: Make sure dependency licenses are okay - command: | - mkdir tmp - npm run check-package-licenses - - fail_fast - - test-framework: - <<: *node-config - resource_class: large - steps: - - checkout - - *remote-docker - - npm_install - - *attach-workspace - - configure_git - - run: - name: Unit test framework components - command: | - npm run test:framework:unit - environment: - CHOKIDAR_USEPOLLING: "1" - NODE_OPTIONS: --max_old_space_size=4096 - - fail_fast - - e2e-project: - <<: *node-config - parameters: - project: - description: The example project to test - type: string - environment: - description: The project environment to use - type: string - default: testing - steps: - - checkout - - npm_install - - configure_remote_cluster - - docker_login - - *attach-workspace - - run: - name: Run e2e test - command: | - cd e2e/projects/<> - git checkout . - cd ~/project - npm run e2e-project -- --project=<> --env=<> --showlog -b - - cleanup_remote_cluster: - filter: <>-testing-ci-$CIRCLE_BUILD_NUM-e2e - - fail_fast - - test-dockerhub: - machine: - <<: *shared-machine-config - steps: - - update_buildx - - checkout - # This is to copy the pre-built code from a previous step - - *attach-workspace - - deploy: - name: Build and test docker images - command: | - bash support/docker-bake-test.sh $CIRCLE_BRANCH - - fail_fast - - dockerhub-release: - machine: - <<: *shared-machine-config - steps: - - update_buildx - - checkout - # This is to copy the pre-built code from a previous step - - *attach-workspace - - docker_login - # TODO: use garden publish here - - deploy: - name: Release docker images - command: | - # TODO: read minor version from package.json file, instead of hardcoding. - export MAJOR_VERSION=0 - export MINOR_VERSION=13 - export CODENAME=bonsai - - if [[ "${CIRCLE_TAG}" = "" ]]; then - # If we don't have a tag, this is an edge release - export PRERELEASE=edge - else - # We have a tag. +setup: true - # Double check that this is an 0.13 version number, because otherwise - # it would be inconsistent with the hardcoded CODENAME export above. - if ! [[ ${CIRCLE_TAG} =~ ^0.13 ]]; then - echo "This pipeline should only build 0.13 releases" - exit 1 - fi - - # Parse SemVer tag into different parts - regex="^([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9A-Za-z-]+))?(\+([0-9A-Za-z-]+))?$" - - # production release, or prerelease - if [[ ${CIRCLE_TAG} =~ $regex ]]; then - export MAJOR_VERSION=${BASH_REMATCH[1]} - export MINOR_VERSION=${BASH_REMATCH[2]} - export PATCH_VERSION=${BASH_REMATCH[3]} - export PRERELEASE=${BASH_REMATCH[5]} - else - echo "Invalid SemVer tag." - exit 1 - fi - fi - - # Build and publish - docker buildx bake --push --progress=plain -f support/docker-bake.hcl all - - fail_fast - - test-docker-gcloud: - docker: - # We do not use a specific digest here on purpose, to use the latest build from the previous job - - image: gardendev/garden-gcloud:bonsai-edge-alpine - environment: - <<: *shared-env-config - GARDEN_TASK_CONCURRENCY_LIMIT: "10" - steps: - # Need to checkout to run example project - - checkout - - configure_remote_cluster - - *attach-workspace - - run: - name: Deploy demo-project with container - # overriding CIRCLE_BUILD_NUM to avoid conflict with other tests - command: CIRCLE_BUILD_NUM=$CIRCLE_BUILD_NUM-docker /garden/garden build --root examples/demo-project --env remote --logger-type basic - - cleanup_remote_cluster: - filter: $CIRCLE_BUILD_NUM-docker - - fail_fast - - github-release-tag: - <<: *release-config - steps: - # Need to checkout to read version from core/package.json - - checkout - - *attach-workspace - - run: - name: Create a release on GitHub. If the release is a pre-release we publish it right away, otherwise we make a draft. - command: | - VERSION="$(cat package.json | jq -r .version)" - PRERELEASE="" - DRAFT=-draft - # If pre-release, we flag it as pre-release and not as a draft - if [[ $VERSION == *"-"* ]]; then DRAFT=""; PRERELEASE=-prerelease; fi - ghr \ - -t ${GITHUB_TOKEN} \ - -u ${CIRCLE_PROJECT_USERNAME} \ - -r ${CIRCLE_PROJECT_REPONAME} \ - -c ${CIRCLE_SHA1} \ - -n ${VERSION} \ - -delete \ - ${PRERELEASE} \ - ${DRAFT} \ - ${VERSION} ./dist - - fail_fast - - github-edge-prerelease: - <<: *release-config - parameters: - version: - description: The version tag/name to set - type: string - steps: - - checkout - - *attach-workspace - - run: - name: Publish a pre-release on GitHub with the valid edge tag - command: | - # We assume that the tag already exists. We update the existing tag - # using the gh cli, and then we upload the artifacts using ghr. - # We do not create a new release here, as this would spam our fellow coder's - # GitHub timelines - VERSION=<> - - # Update the prerelease tag to the current sha - # Github's release edit only changes metadata - # but does not update the underlying tag itself - git tag -f ${VERSION} ${CIRCLE_SHA1} - git push origin --tags --force - - # Update the release to the now updated tag and target - gh release edit ${VERSION} \ - -R ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} \ - --prerelease \ - --target ${CIRCLE_SHA1} \ - --tag ${VERSION} - - # Replace release artifacts - ghr \ - -t ${GITHUB_TOKEN} \ - -u ${CIRCLE_PROJECT_USERNAME} \ - -r ${CIRCLE_PROJECT_REPONAME} \ - -c ${CIRCLE_SHA1} \ - -n ${VERSION} \ - -replace \ - -prerelease \ - ${VERSION} ./dist - - fail_fast - - test-dist: - <<: *node-config - steps: - # Need to checkout to run example project - - checkout - - configure_remote_cluster - - *attach-workspace - - run: - name: Test that the binary works with the fancy logger enabled - command: dist/linux-amd64/garden options - - run: - name: Test the create commands - command: | - mkdir -p /tmp/create-test - cd /tmp/create-test - ~/project/dist/linux-amd64/garden create project --name test-project - - run: - name: Deploy demo-project with binary - # overriding CIRCLE_BUILD_NUM to avoid conflict with other tests - command: CIRCLE_BUILD_NUM=$CIRCLE_BUILD_NUM-dist dist/linux-amd64/garden deploy --root examples/demo-project --env remote --logger-type basic --var userId=$CIRCLE_BUILD_NUM-dist - - cleanup_remote_cluster: - filter: $CIRCLE_BUILD_NUM-dist - - fail_fast - - test-plugins: - machine: - <<: *shared-machine-config - parameters: - kindNodeImage: - description: The kind node image to use - type: string - environment: - <<: *shared-env-config - GARDEN_LOG_LEVEL: debug - steps: - - checkout - - docker_login - - install_kubectl - - install_kind: - kindNodeImage: <> - - configure_git - - npm_install: - context: vm - - *attach-workspace - # Restore Maven cache - - restore_cache: - keys: - - m2-v1 - # Run tests - - run: - name: Plugin tests - command: npm run test:plugins - # Persist Maven cache - - save_cache: - key: m2-v1 - paths: - - ~/.m2 - - fail_fast - - test-kind: - machine: - <<: *shared-machine-config - parameters: - kindNodeImage: - description: The kind node image to use - type: string - environment: - <<: *shared-env-config - GARDEN_LOG_LEVEL: debug - steps: - - checkout - - install_kubectl - - docker_login - - install_kind: - kindNodeImage: <> - - configure_git - - npm_install: - context: vm - - *attach-workspace - - run: - name: Integ tests - command: | - cd core - # Notes: - # - We skip tests that only work for remote environments - # - We currently don't support in-cluster building on kind. - npm run integ-kind - - run: - name: Deploy demo-project - command: ./bin/garden deploy --root examples/demo-project --logger-type basic - - fail_fast - - test-microk8s: - machine: - <<: *shared-machine-config - resource_class: large - parameters: - kubernetesVersion: - description: The Kubernetes version to run - type: string - environment: - <<: *shared-env-config - K8S_VERSION: <> - GARDEN_LOG_LEVEL: debug - steps: - - checkout - - run: - name: Install system dependencies - command: | - sudo apt update - sudo apt install snapd nfs-common - - docker_login - - run: - name: Install and start microk8s - command: | - # create microk8s and snap_microk8s as group aliases for the circleci group - # https://github.com/canonical/microk8s/issues/3608#issuecomment-1383838198 - sudo groupadd --non-unique --gid "$(getent group circleci | cut -f3 -d:)" microk8s - sudo groupadd --non-unique --gid "$(getent group circleci | cut -f3 -d:)" snap_microk8s - - # install microk8s from snap - sudo snap install microk8s --classic --channel=<>/stable - sudo microk8s.status --wait-ready --timeout=300 - - # Workaround for some issue with snap/microk8s - sudo microk8s.enable storage || true - sudo microk8s.enable registry || true - sudo microk8s.enable dns || true - sleep 10 - sudo microk8s.enable storage - sudo microk8s.enable registry - sudo microk8s.enable dns - - echo "********* microk8s ready! ************" - - # Set up kubeconfig and environment - mkdir -p /home/circleci/.kube - sudo sh -c 'microk8s.kubectl config view --raw > /home/circleci/.kube/config' - sudo chown -R circleci:circleci /home/circleci/.kube - echo 'export PATH=/snap/bin:$PATH' >> $BASH_ENV - echo "********* env prepped! *********" - - configure_git - - npm_install: - context: vm - - *attach-workspace - - run: - name: Integ tests - command: | - cd core - # Notes: - # - We skip tests that only work for remote environments - # - We currently don't support in-cluster building on microk8s. - GARDEN_SKIP_TESTS="kaniko remote-only" npm run _integ - - run: - name: Deploy demo-project - command: ./bin/garden deploy --root examples/demo-project --logger-type basic - - fail_fast - - test-minikube: - machine: - <<: *shared-machine-config - resource_class: large - parameters: - minikubeVersion: - description: The Minikube version to use - type: string - default: v1.11.0 - kubernetesVersion: - description: The Kubernetes version to run - type: string - skipTests: - description: Integ test groups to skip - type: string - # Note: By default, we skip tests that only work for remote environments - default: "kaniko remote-only" - remoteCluster: - description: "Configure remote cluster" - type: boolean - default: false - environment: - <<: *shared-env-config - K8S_VERSION: <> - MINIKUBE_VERSION: <> - GARDEN_LOG_LEVEL: debug - steps: - - checkout - - install_kubectl - - run: - name: Install system dependencies - command: | - sudo apt-get update - sudo apt install nfs-common conntrack - - docker_login - - configure_git - - npm_install: - context: vm - - *attach-workspace - - run: - name: Install Minikube Executable - command: | - curl -Lo minikube https://github.com/kubernetes/minikube/releases/download/${MINIKUBE_VERSION}/minikube-linux-amd64 - chmod +x minikube - sudo mv minikube /usr/local/bin - - run: - name: Start Minikube Cluster - command: | - sudo -E minikube start \ - --extra-config=kubeadm.ignore-preflight-errors=NumCPU \ - --extra-config=kubeadm.ignore-preflight-errors=RSRC_INSUFFICIENT_CORES \ - --kubernetes-version=$K8S_VERSION \ - --vm-driver=none \ - --cpus 3 \ - --memory 4096 - sudo chown -R circleci:circleci /home/circleci/.kube /home/circleci/.minikube /etc/kubernetes - # Work around annoying issue on recent minikubes where namespaces take a long time to generate default service account - kubectl create namespace container-default - sleep 10 - - when: - condition: <> - steps: - - configure_remote_cluster - - run: - name: Integ tests - command: | - cd core - GARDEN_SKIP_TESTS="<>" npm run _integ - - run: - name: Deploy demo-project - command: ./bin/garden deploy --root examples/demo-project - - when: - condition: <> - steps: - # NOTE: currently we do not create a namespace in the remote ci cluster during remote integ tests. - # If we start doing that, we need to use the environment variable CIRCLE_BUILD_NUM in the tests. - - cleanup_remote_cluster: - filter: $CIRCLE_BUILD_NUM-remote - - fail_fast - - test-k3s: - machine: - <<: *shared-machine-config - resource_class: large - parameters: - k3sVersion: - description: The k3s version to use - type: string - default: v1.27.4+k3s1 - skipTests: - description: Integ test groups to skip - type: string - default: "kaniko remote-only" - environment: - <<: *shared-env-config - INSTALL_K3S_VERSION: <> - KUBECONFIG: /etc/rancher/k3s/k3s.yaml - GARDEN_LOG_LEVEL: debug - steps: - - checkout - - install_kubectl - - docker_login - - configure_git - - npm_install: - context: vm - - *attach-workspace - - run: - name: Install K3s and start cluster - command: | - curl -sfL https://get.k3s.io | sh -s - --docker --disable=traefik --write-kubeconfig-mode=644 - - run: - name: Integ tests - # Note: We skip tests that only work for remote environments - command: | - cd core - GARDEN_SKIP_TESTS="<>" npm run _integ - - run: - name: Deploy demo-project - command: ./bin/garden deploy --root examples/demo-project - - fail_fast - - test-macos: - macos: - xcode: "13.4.1" - steps: - - checkout - - *attach-workspace - - run: - name: brew install - command: brew install docker kubectl git - # Upgrade git to the latest version. - # This step ensures that Garden is always tested to be compatible with the latest git. - - run: - name: Upgrade git - command: brew upgrade git - - run: - name: Install gcloud SDK - command: | - cd $HOME - curl -LO https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-411.0.0-darwin-x86_64.tar.gz - tar xzf google-cloud-sdk-411.0.0-darwin-x86_64.tar.gz - echo 'export PATH=$HOME/google-cloud-sdk/bin:$PATH' >> $BASH_ENV - - docker_login - - run: - name: Install gke-gcloud-auth-plugin - command: | - gcloud --quiet components install gke-gcloud-auth-plugin - echo 'export USE_GKE_GCLOUD_AUTH_PLUGIN=True' >> $BASH_ENV - - configure_remote_cluster - - run: - name: Deploy demo-project - command: dist/macos-amd64/garden deploy --root examples/demo-project --logger-type basic -l=silly --env remote --var userId=$CIRCLE_BUILD_NUM-macos - - cleanup_remote_cluster: - filter: $CIRCLE_BUILD_NUM-macos - - fail_fast - - test-macos-arm: - macos: - xcode: "13.4.1" - resource_class: macos.m1.medium.gen1 - steps: - - checkout - - *attach-workspace - - run: - name: brew install - command: brew install docker kubectl git - # Upgrade git to the latest version. - # This step ensures that Garden is always tested to be compatible with the latest git. - - run: - name: Upgrade git - command: brew upgrade git - - run: - name: Install gcloud SDK - command: | - cd $HOME - curl -LO https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-411.0.0-darwin-arm.tar.gz - tar xzf google-cloud-sdk-411.0.0-darwin-arm.tar.gz - echo 'export PATH=$HOME/google-cloud-sdk/bin:$PATH' >> $BASH_ENV - - docker_login - - run: - name: Install gke-gcloud-auth-plugin - command: | - gcloud --quiet components install gke-gcloud-auth-plugin - echo 'export USE_GKE_GCLOUD_AUTH_PLUGIN=True' >> $BASH_ENV - - configure_remote_cluster - - run: - name: Deploy demo-project - command: dist/macos-arm64/garden deploy --root examples/demo-project --logger-type basic -l=silly --env remote --var userId=$CIRCLE_BUILD_NUM-macos-arm - - cleanup_remote_cluster: - filter: $CIRCLE_BUILD_NUM-macos-arm - - fail_fast - - test-windows: - executor: win/default - steps: - - checkout - - *attach-workspace - - run: - name: Install Deps - command: | - choco install --limit-output --no-progress -y git - choco install --limit-output --no-progress -y rsync - choco upgrade --limit-output --no-progress -y git rsync gcloudsdk kubernetes-cli - $Env:CLOUDSDK_PYTHON = gcloud components copy-bundled-python - gcloud components install gke-gcloud-auth-plugin --quiet - $Env:USE_GKE_GCLOUD_AUTH_PLUGIN = True - refreshenv - - run: - name: Write gcloud credentials to file - command: $env:GCLOUD_SERVICE_KEY | Set-Content key.json - - run: - name: Setup remote K8s - command: | - gcloud auth activate-service-account --key-file=key.json - $env:GOOGLE_APPLICATION_CREDENTIALS = (Get-Location) + '\key.json' - gcloud --quiet config set project $env:GOOGLE_PROJECT_ID - gcloud --quiet config set compute/zone $env:GOOGLE_COMPUTE_ZONE - gcloud --quiet container clusters get-credentials $env:GOOGLE_CLUSTER_ID --zone $env:GOOGLE_COMPUTE_ZONE - gcloud --quiet auth configure-docker - - run: - name: Deploy demo-project - command: | - .\dist\windows-amd64\garden.exe deploy --root .\examples\demo-project\ --logger-type basic --log-level silly --env remote --force-build --var userId=$env:CIRCLE_BUILD_NUM-win - - run: - name: Cleanup - command: (kubectl delete namespace --wait=false demo-project-testing-$env:CIRCLE_BUILD_NUM-win) -or $true - when: always - - fail_fast +orbs: + path-filtering: circleci/path-filtering@0.0.2 +# We are using a setup workflow here to filter based on the path of changed resources +# and then continue the workflow with continue-config.yml based on the filters. +# So far we only exclude dockerhub tests from running on PRs unless files in ./support changed. workflows: - version: 2 - commit: - jobs: - ### ALL BRANCHES ### - - - build - - build-dist: - requires: [build] - - lint: - requires: [build] - - check-docs: - requires: [build] - - check-package-licenses: - requires: [build] - - test-framework: - requires: [build] - - test-dist: - # Don't attempt to run dist tests for external PRs (they won't have access to the required keys) - <<: *only-internal-prs - requires: [build-dist] - - test-macos: - <<: *only-internal-prs - requires: [build-dist] - - test-macos-arm: - <<: *only-internal-prs - requires: [build-dist] - - test-dockerhub: - <<: *only-prs - requires: [build-dist] - - test-windows: - <<: *only-internal-prs - requires: [build-dist] - - # - e2e-project: - # <<: *only-internal-prs - # name: e2e-code-synchronization - # project: code-synchronization - # requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-demo-project - project: demo-project - environment: remote - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-demo-project-modules - project: demo-project-modules - environment: remote - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-gke-kaniko - project: gke - environment: gke-kaniko - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-gke-buildkit - project: gke - environment: gke-buildkit - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-hadolint - project: hadolint - requires: [build] - # - e2e-project: - # <<: *only-internal-prs - # name: e2e-hadolint-modules - # project: hadolint-modules - # requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-jib-container - project: jib-container - environment: remote - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-jib-container-modules - project: jib-container-modules - environment: remote - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-kustomize - project: kustomize - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-kustomize-modules - project: kustomize-modules - requires: [build] - # - e2e-project: - # <<: *only-internal-prs - # name: e2e-remote-sources - # project: remote-sources - # requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-remote-sources-modules - project: remote-sources-modules - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-run-actions - project: run-actions - requires: [build] - # - e2e-project: - # <<: *only-internal-prs - # name: e2e-tasks-modules - # project: tasks-modules - # requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-templated-k8s-container - project: templated-k8s-container - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-templated-k8s-container-modules - project: templated-k8s-container-modules - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-vote - project: vote - environment: remote - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-vote-modules - project: vote-modules - environment: remote - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-vote-helm - project: vote-helm - requires: [build] - - e2e-project: - <<: *only-internal-prs - name: e2e-open-telemetry - project: open-telemetry - requires: [build] - # - e2e-project: - # <<: *only-internal-prs - # name: e2e-vote-helm-modules - # project: vote-helm-modules - # requires: [build] - - ### REMOTE TESTS ### - # The remote tests (e.g. kaniko and buildkit) still require a local kubernetes cluster for some reason… - - test-minikube: - <<: *only-internal-prs - name: test-remote - requires: [build] - kubernetesVersion: "1.23.3" - minikubeVersion: "v1.25.2" - skipTests: "local-only" - remoteCluster: true - - ### VM TESTS ### - - # Note: The below is a not-quite-random mix of local k8s variants and k8s versions. Doing a full matrix of every - # variant and k8s version would be quite expensive, so we try and make sure each of the latest 6-7 k8s versions is - # tested, and that the most recent versions are broadly tested. The kind tests are the cheapest to run so we use many - # of those, but they currently don't test in-cluster building, so we do need a range of versions on minikube as well. - - test-minikube: - name: vm-1.22-minikube - requires: [build] - kubernetesVersion: "1.22.2" - minikubeVersion: "v1.25.2" - - test-minikube: - name: vm-1.23-minikube - requires: [build] - kubernetesVersion: "1.23.3" - minikubeVersion: "v1.25.2" - - test-microk8s: - name: vm-1.24-microk8s - requires: [build] - kubernetesVersion: "1.24" - - test-microk8s: - name: vm-1.25-microk8s - requires: [build] - kubernetesVersion: "1.25" - - test-microk8s: - name: vm-1.26-microk8s - requires: [build] - kubernetesVersion: "1.26" - - test-kind: - name: vm-1.21-kind - requires: [build] - kindNodeImage: kindest/node:v1.21.14@sha256:27ef72ea623ee879a25fe6f9982690a3e370c68286f4356bf643467c552a3888 - # - test-kind: - # name: vm-1.22-kind - # requires: [build] - # kindNodeImage: kindest/node:v1.22.17@sha256:c8a828709a53c25cbdc0790c8afe12f25538617c7be879083248981945c38693 - # - test-kind: - # name: vm-1.23-kind - # requires: [build] - # kindNodeImage: kindest/node:v1.23.17@sha256:e5fd1d9cd7a9a50939f9c005684df5a6d145e8d695e78463637b79464292e66c - - test-kind: - name: vm-1.24-kind - requires: [build] - kindNodeImage: kindest/node:v1.24.12@sha256:1e12918b8bc3d4253bc08f640a231bb0d3b2c5a9b28aa3f2ca1aee93e1e8db16 - # - test-kind: - # name: vm-1.25-kind - # requires: [build] - # kindNodeImage: kindest/node:v1.25.8@sha256:00d3f5314cc35327706776e95b2f8e504198ce59ac545d0200a89e69fce10b7f - - test-kind: - name: vm-1.26-kind - requires: [build] - kindNodeImage: kindest/node:v1.26.3@sha256:61b92f38dff6ccc29969e7aa154d34e38b89443af1a2c14e6cfbd2df6419c66f - - test-k3s: - name: vm-1.27-k3s - requires: [build] - # version v1.27.4+k3s1 fails with this issue https://github.com/moby/moby/issues/45935 - k3sVersion: v1.27.2+k3s1 - - - test-plugins: - <<: *only-internal-prs - requires: [build] - kindNodeImage: kindest/node:v1.21.14@sha256:27ef72ea623ee879a25fe6f9982690a3e370c68286f4356bf643467c552a3888 - - # This is only for edge release (Overrides version to edge-bonsai) - - build-dist: - <<: *only-main - name: build-dist-edge - version: edge-bonsai - requires: [build] - - - github-edge-prerelease: - <<: *only-main - version: edge-bonsai - requires: [build-dist-edge] - - - dockerhub-release: - <<: *only-main - context: docker - requires: - - build-dist-edge - - test-docker-gcloud: - context: docker - requires: [dockerhub-release] - tags: + setup-workflow: jobs: - - build: - <<: *only-tags - - build-dist: - <<: *only-tags - requires: [build] - - dockerhub-release: - <<: *only-tags - context: docker - requires: [build-dist] - - github-release-tag: - <<: *only-tags - requires: [build-dist] + - path-filtering/filter: + base-revision: main + config-path: .circleci/continue-config.yml + mapping: | + support/.* run-test-dockerhub true + .circleci/.* run-test-dockerhub true \ No newline at end of file diff --git a/.circleci/continue-config.yml b/.circleci/continue-config.yml new file mode 100644 index 0000000000..a245a360a9 --- /dev/null +++ b/.circleci/continue-config.yml @@ -0,0 +1,1238 @@ +# CircleCI 2.1 configuration file +version: 2.1 + +orbs: + win: circleci/windows@2.2.0 + rok8s-scripts: fairwinds/rok8s-scripts@11.1.3 + +parameters: + run-test-dockerhub: + type: boolean + default: false + +# Shared config to use between jobs +# These can be used to inject shared variables +# see https://blog.daemonl.com/2016/02/yaml.html +.references: + shared-env-config: &shared-env-config + GARDEN_DISABLE_VERSION_CHECK: "true" + GARDEN_DISABLE_ANALYTICS: "true" + GARDEN_K8S_BUILD_SYNC_MODE: "mutagen" + + shared-machine-config: &shared-machine-config + image: "ubuntu-2204:2023.02.1" + docker_layer_caching: true + + remote-docker: &remote-docker + setup_remote_docker: + version: 20.10.24 + docker_layer_caching: true + + runner-image: &runner-image + image: gardendev/circleci-runner:18.15.0-1@sha256:c830e29ab30a1c5b08cba4d041d3325ef6958aebeba1b10b1ee9566d7b1a4d42 + + # Configuration for our node jobs + node-config: &node-config + docker: + - <<: *runner-image + environment: + <<: *shared-env-config + resource_class: medium + + # Configuration for release jobs + release-config: &release-config + docker: + - <<: *runner-image + + # Attaches the current saved workspace + attach-workspace: &attach-workspace + attach_workspace: + at: ./ + + only-prs: &only-prs + filters: + branches: + ignore: main + tags: + ignore: /.*/ + + # Only run jobs on main branch + only-main: &only-main + filters: + branches: + only: + - main + tags: + ignore: /.*/ + + # Only run on versioned tags + only-tags: &only-tags + filters: + branches: + ignore: /.*/ + tags: + only: /\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?/ + + # Only run for PRs from core team + only-internal-prs: &only-internal-prs + filters: + branches: + # Forked pull requests have CIRCLE_BRANCH set to pull/XXX + ignore: /pull\/[0-9]+/ + +# Reuseable commands to execute in jobs +# see https://circleci.com/docs/2.0/configuration-reference/#commands-requires-version21 +# and example https://github.com/mapbox/mapbox-gl-native/blob/master/circle.yml +commands: + npm_install: + description: | + Installs npm packages and loads and saves the caches as appropriate + parameters: + context: + description: Set this to vm if installing in a VM, to avoid conflicting caches with the docker runs + type: string + default: docker + steps: + - restore_cache: + keys: + - npm-v2-<>-{{ checksum "package-lock.json" }} + + - run: npm ci + + - save_cache: + key: npm-v2-<>-{{ checksum "package-lock.json" }} + paths: + - node_modules + - cli/node_modules + - core/node_modules + - e2e/node_modules + - plugins/conftest/node_modules + - plugins/conftest-container/node_modules + - plugins/conftest-kubernetes/node_modules + - plugins/jib/node_modules + - plugins/maven-container/node_modules + - plugins/pulumi/node_modules + - plugins/terraform/node_modules + - sdk/node_modules + + configure_git: + description: Configure git (needed for some tests) + steps: + - run: + name: Configure git + # ensure that file transfer protocol is allowed, see https://vielmetti.typepad.com/logbook/2022/10/git-security-fixes-lead-to-fatal-transport-file-not-allowed-error-in-ci-systems-cve-2022-39253.html + command: | + git config --global user.name "Garden CI" + git config --global user.email "admin@garden.io" + git config --global protocol.file.allow "always" + + install_kubectl: + description: Install kubectl + steps: + - run: + name: Install binary dependencies + command: | + mkdir -p $HOME/bin + cd $HOME/bin + curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/amd64/kubectl + chmod +x kubectl + echo 'export PATH=$HOME/bin:$PATH' >> $BASH_ENV + + docker_login: + description: Login to Docker Hub + steps: + - run: + name: docker login + command: | + if [ -n "$DOCKER_PASS" ]; then + echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin + else + echo "Skipping, no login available" + fi + + install_kind: + description: Install Kind + parameters: + kindNodeImage: + description: The kind node image to use + type: string + steps: + - run: + name: Install kind + command: | + curl -LO https://github.com/kubernetes-sigs/kind/releases/download/v0.18.0/kind-linux-amd64 + chmod +x kind-linux-amd64 + sudo mv kind-linux-amd64 /usr/local/bin/kind + - run: + name: Start kind cluster + command: | + # Create the kind cluster with a custom config to enable the default ingress controller + cat \<> \ + --wait=600s \ + --config=- + + kind: Cluster + apiVersion: kind.x-k8s.io/v1alpha4 + nodes: + - role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + authorization-mode: "AlwaysAllow" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP + EOF + + kubectl config set-context kind-kind + + configure_remote_cluster: + description: Configure the kubectl context via gcloud so that we can access our remote cluster. Used for e2e testing. + steps: + - run: + name: Configure kubectl context via gcloud and authenticate to Google Container Registry + command: | + export USE_GKE_GCLOUD_AUTH_PLUGIN=True + echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> $BASH_ENV + export GOOGLE_APPLICATION_CREDENTIALS=$HOME/gcloud-key.json + echo "export GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_APPLICATION_CREDENTIALS" >> $BASH_ENV + echo $GCLOUD_SERVICE_KEY > $GOOGLE_APPLICATION_CREDENTIALS + gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS + gcloud --quiet config set project $GOOGLE_PROJECT_ID + gcloud --quiet config set compute/zone $GOOGLE_COMPUTE_ZONE + gcloud --quiet container clusters get-credentials $GOOGLE_CLUSTER_ID --zone $GOOGLE_COMPUTE_ZONE + gcloud --quiet auth configure-docker + + cleanup_remote_cluster: + description: Clean up namespaces in the ci cluster on gcloud (to be used with configure_remote_cluster) + parameters: + filter: + description: What to grep namespaces by to select the current namespace to delete + type: string + steps: + - run: + name: Delete current namespace(s) + command: kubectl get ns | grep <> | awk '{print $1}' | xargs -n 1 kubectl delete namespace --wait=false || true + when: always + - run: + name: Delete namespaces older than 1 hour + # hack: find namespaces that contain '-ci' and their age ends with h or d, e.g. 1d5h or 24h + command: kubectl get ns | grep -E '(d|h)$' | grep -- '-testing' | awk '{print $1}' | xargs -n 1 kubectl delete namespace --wait=false || true + when: always + + build_dist: + description: Package built code into executables and persist to dist directory + parameters: + version: + description: | + The version tag used when building. Use to set the version string in the generated zip file names, + e.g. when creating unstable releases. The script defaults to using the version from core/package.json. + type: string + default: "" + steps: + # We need Docker for building the Alpine package + - *remote-docker + - checkout + - npm_install + - *attach-workspace + - restore_cache: + keys: + - pkg-v3-{{ checksum "package-lock.json" }} + - run: + name: Install Codesigning utility (needed for ARM64 on MacOS) + command: | + curl -Lo ldid https://github.com/ProcursusTeam/ldid/releases/download/v2.1.5-procursus7/ldid_linux_x86_64 + chmod +x ldid + sudo mv ldid /usr/local/bin + - run: + name: Setup buildx and qemu for cross-platform builds + command: | + sudo apt-get update + sudo apt-get install -y qemu-user-static + sudo apt-get install -y binfmt-support + - run: + name: Run dist script + command: npm run dist -- --version "<>" + - persist_to_workspace: + root: ./ + paths: + - dist/ + # Needed for the alpine docker build + - tmp/pkg/ + - save_cache: + key: pkg-v3-{{ checksum "package-lock.json" }} + paths: + - tmp/pkg-fetch + - run: + # No need to store the raw files as artifacts, we just want the archives + name: Cleanup + command: rm -rf dist/*-amd64 && rm -rf dist/*-arm64 + - store_artifacts: + path: dist + destination: dist + update_buildx: + description: Update buildx to a version that supports syntax in bakefile + steps: + - run: + name: Update buildx + command: | + mkdir -p ~/.docker/cli-plugins + wget -O ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.11.1/buildx-v0.11.1.linux-amd64 + echo "34927047282ef9052f57809fe94783b2dc0ab556fdd60c2c0b7f4e6e5f05a53b ${HOME}/.docker/cli-plugins/docker-buildx" | sha256sum -c + chmod +x ~/.docker/cli-plugins/docker-buildx + fail_fast: + description: Fail the whole workflow if this job fails in the merge queue + steps: + - run: + name: Fail Fast + when: on_fail + command: | + if [[ "${CIRCLE_BRANCH}" == "gh-readonly-queue"* ]]; then + echo "Canceling workflow as a step resulted in failure" + curl -X POST --header "Content-Type: application/json" "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}/cancel?circle-token=${CIRCLE_TOKEN}" + else + echo "Not canceling workflow as not running in merge queue" + fi + +# +# Jobs section +# +jobs: + build: + <<: *node-config + steps: + - checkout + - npm_install + - run: + name: build + command: | + npm run build + # Save the built output to be used for the docker image and for the release steps + - persist_to_workspace: + # Must be an absolute path, or relative path from working_directory. This is a directory on the container which is + # taken to be the root directory of the workspace. + root: ./ + # Must be relative path from root + paths: + # Save the built output for future + - cli/build/ + - core/build/ + - static/ + # TODO: see if we can make this somewhat more specific + - sdk/ + - plugins/ + - e2e/ + - fail_fast + + build-dist: + <<: *node-config + resource_class: xlarge + parameters: + version: + description: The version tag/name to set + type: string + default: "" + steps: + - build_dist: + version: <> + - fail_fast + + lint: + <<: *node-config + resource_class: large + steps: + - checkout + - npm_install + - *attach-workspace + - run: + name: lint + command: npm run lint + - fail_fast + + check-docs: + <<: *node-config + steps: + - checkout + - npm_install + - *attach-workspace + - run: + name: Make sure generated docs are up-to-date + command: npm run check-docs + - fail_fast + + check-package-licenses: + <<: *node-config + steps: + - checkout + - npm_install + - *attach-workspace + - run: + name: Make sure dependency licenses are okay + command: | + mkdir tmp + npm run check-package-licenses + - fail_fast + + test-framework: + <<: *node-config + resource_class: large + steps: + - checkout + - *remote-docker + - npm_install + - *attach-workspace + - configure_git + - run: + name: Unit test framework components + command: | + npm run test:framework:unit + environment: + CHOKIDAR_USEPOLLING: "1" + NODE_OPTIONS: --max_old_space_size=4096 + - fail_fast + + e2e-project: + <<: *node-config + parameters: + project: + description: The example project to test + type: string + environment: + description: The project environment to use + type: string + default: testing + steps: + - checkout + - npm_install + - configure_remote_cluster + - docker_login + - *attach-workspace + - run: + name: Run e2e test + command: | + cd e2e/projects/<> + git checkout . + cd ~/project + npm run e2e-project -- --project=<> --env=<> --showlog -b + - cleanup_remote_cluster: + filter: <>-testing-ci-$CIRCLE_BUILD_NUM-e2e + - fail_fast + + test-dockerhub: + machine: + <<: *shared-machine-config + steps: + # Only run test-dockerhub if path-filter noticed changes in ./support/* + - when: + condition: <> + steps: + - update_buildx + - checkout + # This is to copy the pre-built code from a previous step + - *attach-workspace + - deploy: + name: Build and test docker images + command: | + bash support/docker-bake-test.sh $CIRCLE_BRANCH + - fail_fast + - unless: + condition: <> + steps: + - run: echo "Skipping test-dockerhub because no changes in ./support/*" + + dockerhub-release: + machine: + <<: *shared-machine-config + steps: + - update_buildx + - checkout + # This is to copy the pre-built code from a previous step + - *attach-workspace + - docker_login + # TODO: use garden publish here + - deploy: + name: Release docker images + command: | + # TODO: read minor version from package.json file, instead of hardcoding. + export MAJOR_VERSION=0 + export MINOR_VERSION=13 + export CODENAME=bonsai + + if [[ "${CIRCLE_TAG}" = "" ]]; then + # If we don't have a tag, this is an edge release + export PRERELEASE=edge + else + # We have a tag. + + # Double check that this is an 0.13 version number, because otherwise + # it would be inconsistent with the hardcoded CODENAME export above. + if ! [[ ${CIRCLE_TAG} =~ ^0.13 ]]; then + echo "This pipeline should only build 0.13 releases" + exit 1 + fi + + # Parse SemVer tag into different parts + regex="^([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9A-Za-z-]+))?(\+([0-9A-Za-z-]+))?$" + + # production release, or prerelease + if [[ ${CIRCLE_TAG} =~ $regex ]]; then + export MAJOR_VERSION=${BASH_REMATCH[1]} + export MINOR_VERSION=${BASH_REMATCH[2]} + export PATCH_VERSION=${BASH_REMATCH[3]} + export PRERELEASE=${BASH_REMATCH[5]} + else + echo "Invalid SemVer tag." + exit 1 + fi + fi + + # Build and publish + docker buildx bake --push --progress=plain -f support/docker-bake.hcl all + - fail_fast + + test-docker-gcloud: + docker: + # We do not use a specific digest here on purpose, to use the latest build from the previous job + - image: gardendev/garden-gcloud:bonsai-edge-alpine + environment: + <<: *shared-env-config + GARDEN_TASK_CONCURRENCY_LIMIT: "10" + steps: + # Need to checkout to run example project + - checkout + - configure_remote_cluster + - *attach-workspace + - run: + name: Deploy demo-project with container + # overriding CIRCLE_BUILD_NUM to avoid conflict with other tests + command: CIRCLE_BUILD_NUM=$CIRCLE_BUILD_NUM-docker /garden/garden build --root examples/demo-project --env remote --logger-type basic + - cleanup_remote_cluster: + filter: $CIRCLE_BUILD_NUM-docker + - fail_fast + + github-release-tag: + <<: *release-config + steps: + # Need to checkout to read version from core/package.json + - checkout + - *attach-workspace + - run: + name: Create a release on GitHub. If the release is a pre-release we publish it right away, otherwise we make a draft. + command: | + VERSION="$(cat package.json | jq -r .version)" + PRERELEASE="" + DRAFT=-draft + # If pre-release, we flag it as pre-release and not as a draft + if [[ $VERSION == *"-"* ]]; then DRAFT=""; PRERELEASE=-prerelease; fi + ghr \ + -t ${GITHUB_TOKEN} \ + -u ${CIRCLE_PROJECT_USERNAME} \ + -r ${CIRCLE_PROJECT_REPONAME} \ + -c ${CIRCLE_SHA1} \ + -n ${VERSION} \ + -delete \ + ${PRERELEASE} \ + ${DRAFT} \ + ${VERSION} ./dist + - fail_fast + + github-edge-prerelease: + <<: *release-config + parameters: + version: + description: The version tag/name to set + type: string + steps: + - checkout + - *attach-workspace + - run: + name: Publish a pre-release on GitHub with the valid edge tag + command: | + # We assume that the tag already exists. We update the existing tag + # using the gh cli, and then we upload the artifacts using ghr. + # We do not create a new release here, as this would spam our fellow coder's + # GitHub timelines + VERSION=<> + + # Update the prerelease tag to the current sha + # Github's release edit only changes metadata + # but does not update the underlying tag itself + git tag -f ${VERSION} ${CIRCLE_SHA1} + git push origin --tags --force + + # Update the release to the now updated tag and target + gh release edit ${VERSION} \ + -R ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} \ + --prerelease \ + --target ${CIRCLE_SHA1} \ + --tag ${VERSION} + + # Replace release artifacts + ghr \ + -t ${GITHUB_TOKEN} \ + -u ${CIRCLE_PROJECT_USERNAME} \ + -r ${CIRCLE_PROJECT_REPONAME} \ + -c ${CIRCLE_SHA1} \ + -n ${VERSION} \ + -replace \ + -prerelease \ + ${VERSION} ./dist + - fail_fast + + test-dist: + <<: *node-config + steps: + # Need to checkout to run example project + - checkout + - configure_remote_cluster + - *attach-workspace + - run: + name: Test that the binary works with the fancy logger enabled + command: dist/linux-amd64/garden options + - run: + name: Test the create commands + command: | + mkdir -p /tmp/create-test + cd /tmp/create-test + ~/project/dist/linux-amd64/garden create project --name test-project + - run: + name: Deploy demo-project with binary + # overriding CIRCLE_BUILD_NUM to avoid conflict with other tests + command: CIRCLE_BUILD_NUM=$CIRCLE_BUILD_NUM-dist dist/linux-amd64/garden deploy --root examples/demo-project --env remote --logger-type basic --var userId=$CIRCLE_BUILD_NUM-dist + - cleanup_remote_cluster: + filter: $CIRCLE_BUILD_NUM-dist + - fail_fast + + test-plugins: + machine: + <<: *shared-machine-config + parameters: + kindNodeImage: + description: The kind node image to use + type: string + environment: + <<: *shared-env-config + GARDEN_LOG_LEVEL: debug + steps: + - checkout + - docker_login + - install_kubectl + - install_kind: + kindNodeImage: <> + - configure_git + - npm_install: + context: vm + - *attach-workspace + # Restore Maven cache + - restore_cache: + keys: + - m2-v1 + # Run tests + - run: + name: Plugin tests + command: npm run test:plugins + # Persist Maven cache + - save_cache: + key: m2-v1 + paths: + - ~/.m2 + - fail_fast + + test-kind: + machine: + <<: *shared-machine-config + parameters: + kindNodeImage: + description: The kind node image to use + type: string + environment: + <<: *shared-env-config + GARDEN_LOG_LEVEL: debug + steps: + - checkout + - install_kubectl + - docker_login + - install_kind: + kindNodeImage: <> + - configure_git + - npm_install: + context: vm + - *attach-workspace + - run: + name: Integ tests + command: | + cd core + # Notes: + # - We skip tests that only work for remote environments + # - We currently don't support in-cluster building on kind. + npm run integ-kind + - run: + name: Deploy demo-project + command: ./bin/garden deploy --root examples/demo-project --logger-type basic + - fail_fast + + test-microk8s: + machine: + <<: *shared-machine-config + resource_class: large + parameters: + kubernetesVersion: + description: The Kubernetes version to run + type: string + environment: + <<: *shared-env-config + K8S_VERSION: <> + GARDEN_LOG_LEVEL: debug + steps: + - checkout + - run: + name: Install system dependencies + command: | + sudo apt update + sudo apt install snapd nfs-common + - docker_login + - run: + name: Install and start microk8s + command: | + # create microk8s and snap_microk8s as group aliases for the circleci group + # https://github.com/canonical/microk8s/issues/3608#issuecomment-1383838198 + sudo groupadd --non-unique --gid "$(getent group circleci | cut -f3 -d:)" microk8s + sudo groupadd --non-unique --gid "$(getent group circleci | cut -f3 -d:)" snap_microk8s + + # install microk8s from snap + sudo snap install microk8s --classic --channel=<>/stable + sudo microk8s.status --wait-ready --timeout=300 + + # Workaround for some issue with snap/microk8s + sudo microk8s.enable storage || true + sudo microk8s.enable registry || true + sudo microk8s.enable dns || true + sleep 10 + sudo microk8s.enable storage + sudo microk8s.enable registry + sudo microk8s.enable dns + + echo "********* microk8s ready! ************" + + # Set up kubeconfig and environment + mkdir -p /home/circleci/.kube + sudo sh -c 'microk8s.kubectl config view --raw > /home/circleci/.kube/config' + sudo chown -R circleci:circleci /home/circleci/.kube + echo 'export PATH=/snap/bin:$PATH' >> $BASH_ENV + echo "********* env prepped! *********" + - configure_git + - npm_install: + context: vm + - *attach-workspace + - run: + name: Integ tests + command: | + cd core + # Notes: + # - We skip tests that only work for remote environments + # - We currently don't support in-cluster building on microk8s. + GARDEN_SKIP_TESTS="kaniko remote-only" npm run _integ + - run: + name: Deploy demo-project + command: ./bin/garden deploy --root examples/demo-project --logger-type basic + - fail_fast + + test-minikube: + machine: + <<: *shared-machine-config + resource_class: large + parameters: + minikubeVersion: + description: The Minikube version to use + type: string + default: v1.11.0 + kubernetesVersion: + description: The Kubernetes version to run + type: string + skipTests: + description: Integ test groups to skip + type: string + # Note: By default, we skip tests that only work for remote environments + default: "kaniko remote-only" + remoteCluster: + description: "Configure remote cluster" + type: boolean + default: false + environment: + <<: *shared-env-config + K8S_VERSION: <> + MINIKUBE_VERSION: <> + GARDEN_LOG_LEVEL: debug + steps: + - checkout + - install_kubectl + - run: + name: Install system dependencies + command: | + sudo apt-get update + sudo apt install nfs-common conntrack + - docker_login + - configure_git + - npm_install: + context: vm + - *attach-workspace + - run: + name: Install Minikube Executable + command: | + curl -Lo minikube https://github.com/kubernetes/minikube/releases/download/${MINIKUBE_VERSION}/minikube-linux-amd64 + chmod +x minikube + sudo mv minikube /usr/local/bin + - run: + name: Start Minikube Cluster + command: | + sudo -E minikube start \ + --extra-config=kubeadm.ignore-preflight-errors=NumCPU \ + --extra-config=kubeadm.ignore-preflight-errors=RSRC_INSUFFICIENT_CORES \ + --kubernetes-version=$K8S_VERSION \ + --vm-driver=none \ + --cpus 3 \ + --memory 4096 + sudo chown -R circleci:circleci /home/circleci/.kube /home/circleci/.minikube /etc/kubernetes + # Work around annoying issue on recent minikubes where namespaces take a long time to generate default service account + kubectl create namespace container-default + sleep 10 + - when: + condition: <> + steps: + - configure_remote_cluster + - run: + name: Integ tests + command: | + cd core + GARDEN_SKIP_TESTS="<>" npm run _integ + - run: + name: Deploy demo-project + command: ./bin/garden deploy --root examples/demo-project + - when: + condition: <> + steps: + # NOTE: currently we do not create a namespace in the remote ci cluster during remote integ tests. + # If we start doing that, we need to use the environment variable CIRCLE_BUILD_NUM in the tests. + - cleanup_remote_cluster: + filter: $CIRCLE_BUILD_NUM-remote + - fail_fast + + test-k3s: + machine: + <<: *shared-machine-config + resource_class: large + parameters: + k3sVersion: + description: The k3s version to use + type: string + default: v1.27.4+k3s1 + skipTests: + description: Integ test groups to skip + type: string + default: "kaniko remote-only" + environment: + <<: *shared-env-config + INSTALL_K3S_VERSION: <> + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + GARDEN_LOG_LEVEL: debug + steps: + - checkout + - install_kubectl + - docker_login + - configure_git + - npm_install: + context: vm + - *attach-workspace + - run: + name: Install K3s and start cluster + command: | + curl -sfL https://get.k3s.io | sh -s - --docker --disable=traefik --write-kubeconfig-mode=644 + - run: + name: Integ tests + # Note: We skip tests that only work for remote environments + command: | + cd core + GARDEN_SKIP_TESTS="<>" npm run _integ + - run: + name: Deploy demo-project + command: ./bin/garden deploy --root examples/demo-project + - fail_fast + + test-macos: + macos: + xcode: "13.4.1" + steps: + - checkout + - *attach-workspace + - run: + name: brew install + command: brew install docker kubectl git + # Upgrade git to the latest version. + # This step ensures that Garden is always tested to be compatible with the latest git. + - run: + name: Upgrade git + command: brew upgrade git + - run: + name: Install gcloud SDK + command: | + cd $HOME + curl -LO https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-411.0.0-darwin-x86_64.tar.gz + tar xzf google-cloud-sdk-411.0.0-darwin-x86_64.tar.gz + echo 'export PATH=$HOME/google-cloud-sdk/bin:$PATH' >> $BASH_ENV + - docker_login + - run: + name: Install gke-gcloud-auth-plugin + command: | + gcloud --quiet components install gke-gcloud-auth-plugin + echo 'export USE_GKE_GCLOUD_AUTH_PLUGIN=True' >> $BASH_ENV + - configure_remote_cluster + - run: + name: Deploy demo-project + command: dist/macos-amd64/garden deploy --root examples/demo-project --logger-type basic -l=silly --env remote --var userId=$CIRCLE_BUILD_NUM-macos + - cleanup_remote_cluster: + filter: $CIRCLE_BUILD_NUM-macos + - fail_fast + + test-macos-arm: + macos: + xcode: "13.4.1" + resource_class: macos.m1.medium.gen1 + steps: + - checkout + - *attach-workspace + - run: + name: brew install + command: brew install docker kubectl git + # Upgrade git to the latest version. + # This step ensures that Garden is always tested to be compatible with the latest git. + - run: + name: Upgrade git + command: brew upgrade git + - run: + name: Install gcloud SDK + command: | + cd $HOME + curl -LO https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-411.0.0-darwin-arm.tar.gz + tar xzf google-cloud-sdk-411.0.0-darwin-arm.tar.gz + echo 'export PATH=$HOME/google-cloud-sdk/bin:$PATH' >> $BASH_ENV + - docker_login + - run: + name: Install gke-gcloud-auth-plugin + command: | + gcloud --quiet components install gke-gcloud-auth-plugin + echo 'export USE_GKE_GCLOUD_AUTH_PLUGIN=True' >> $BASH_ENV + - configure_remote_cluster + - run: + name: Deploy demo-project + command: dist/macos-arm64/garden deploy --root examples/demo-project --logger-type basic -l=silly --env remote --var userId=$CIRCLE_BUILD_NUM-macos-arm + - cleanup_remote_cluster: + filter: $CIRCLE_BUILD_NUM-macos-arm + - fail_fast + + test-windows: + executor: win/default + steps: + - checkout + - *attach-workspace + - run: + name: Install Deps + command: | + choco install --limit-output --no-progress -y git + choco install --limit-output --no-progress -y rsync + choco upgrade --limit-output --no-progress -y git rsync gcloudsdk kubernetes-cli + $Env:CLOUDSDK_PYTHON = gcloud components copy-bundled-python + gcloud components install gke-gcloud-auth-plugin --quiet + $Env:USE_GKE_GCLOUD_AUTH_PLUGIN = True + refreshenv + - run: + name: Write gcloud credentials to file + command: $env:GCLOUD_SERVICE_KEY | Set-Content key.json + - run: + name: Setup remote K8s + command: | + gcloud auth activate-service-account --key-file=key.json + $env:GOOGLE_APPLICATION_CREDENTIALS = (Get-Location) + '\key.json' + gcloud --quiet config set project $env:GOOGLE_PROJECT_ID + gcloud --quiet config set compute/zone $env:GOOGLE_COMPUTE_ZONE + gcloud --quiet container clusters get-credentials $env:GOOGLE_CLUSTER_ID --zone $env:GOOGLE_COMPUTE_ZONE + gcloud --quiet auth configure-docker + - run: + name: Deploy demo-project + command: | + .\dist\windows-amd64\garden.exe deploy --root .\examples\demo-project\ --logger-type basic --log-level silly --env remote --force-build --var userId=$env:CIRCLE_BUILD_NUM-win + - run: + name: Cleanup + command: (kubectl delete namespace --wait=false demo-project-testing-$env:CIRCLE_BUILD_NUM-win) -or $true + when: always + - fail_fast + +workflows: + version: 2 + + commit: + jobs: + ### ALL BRANCHES ### + + - build + - build-dist: + requires: [build] + - lint: + requires: [build] + - check-docs: + requires: [build] + - check-package-licenses: + requires: [build] + - test-framework: + requires: [build] + - test-dist: + # Don't attempt to run dist tests for external PRs (they won't have access to the required keys) + <<: *only-internal-prs + requires: [build-dist] + - test-macos: + <<: *only-internal-prs + requires: [build-dist] + - test-macos-arm: + <<: *only-internal-prs + requires: [build-dist] + - test-dockerhub: + <<: *only-prs + requires: [build-dist] + - test-windows: + <<: *only-internal-prs + requires: [build-dist] + + # - e2e-project: + # <<: *only-internal-prs + # name: e2e-code-synchronization + # project: code-synchronization + # requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-demo-project + project: demo-project + environment: remote + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-demo-project-modules + project: demo-project-modules + environment: remote + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-gke-kaniko + project: gke + environment: gke-kaniko + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-gke-buildkit + project: gke + environment: gke-buildkit + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-hadolint + project: hadolint + requires: [build] + # - e2e-project: + # <<: *only-internal-prs + # name: e2e-hadolint-modules + # project: hadolint-modules + # requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-jib-container + project: jib-container + environment: remote + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-jib-container-modules + project: jib-container-modules + environment: remote + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-kustomize + project: kustomize + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-kustomize-modules + project: kustomize-modules + requires: [build] + # - e2e-project: + # <<: *only-internal-prs + # name: e2e-remote-sources + # project: remote-sources + # requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-remote-sources-modules + project: remote-sources-modules + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-run-actions + project: run-actions + requires: [build] + # - e2e-project: + # <<: *only-internal-prs + # name: e2e-tasks-modules + # project: tasks-modules + # requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-templated-k8s-container + project: templated-k8s-container + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-templated-k8s-container-modules + project: templated-k8s-container-modules + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-vote + project: vote + environment: remote + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-vote-modules + project: vote-modules + environment: remote + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-vote-helm + project: vote-helm + requires: [build] + - e2e-project: + <<: *only-internal-prs + name: e2e-open-telemetry + project: open-telemetry + requires: [build] + # - e2e-project: + # <<: *only-internal-prs + # name: e2e-vote-helm-modules + # project: vote-helm-modules + # requires: [build] + + ### REMOTE TESTS ### + # The remote tests (e.g. kaniko and buildkit) still require a local kubernetes cluster for some reason… + - test-minikube: + <<: *only-internal-prs + name: test-remote + requires: [build] + kubernetesVersion: "1.23.3" + minikubeVersion: "v1.25.2" + skipTests: "local-only" + remoteCluster: true + + ### VM TESTS ### + + # Note: The below is a not-quite-random mix of local k8s variants and k8s versions. Doing a full matrix of every + # variant and k8s version would be quite expensive, so we try and make sure each of the latest 6-7 k8s versions is + # tested, and that the most recent versions are broadly tested. The kind tests are the cheapest to run so we use many + # of those, but they currently don't test in-cluster building, so we do need a range of versions on minikube as well. + - test-minikube: + name: vm-1.22-minikube + requires: [build] + kubernetesVersion: "1.22.2" + minikubeVersion: "v1.25.2" + - test-minikube: + name: vm-1.23-minikube + requires: [build] + kubernetesVersion: "1.23.3" + minikubeVersion: "v1.25.2" + - test-microk8s: + name: vm-1.24-microk8s + requires: [build] + kubernetesVersion: "1.24" + - test-microk8s: + name: vm-1.25-microk8s + requires: [build] + kubernetesVersion: "1.25" + - test-microk8s: + name: vm-1.26-microk8s + requires: [build] + kubernetesVersion: "1.26" + - test-kind: + name: vm-1.21-kind + requires: [build] + kindNodeImage: kindest/node:v1.21.14@sha256:27ef72ea623ee879a25fe6f9982690a3e370c68286f4356bf643467c552a3888 + # - test-kind: + # name: vm-1.22-kind + # requires: [build] + # kindNodeImage: kindest/node:v1.22.17@sha256:c8a828709a53c25cbdc0790c8afe12f25538617c7be879083248981945c38693 + # - test-kind: + # name: vm-1.23-kind + # requires: [build] + # kindNodeImage: kindest/node:v1.23.17@sha256:e5fd1d9cd7a9a50939f9c005684df5a6d145e8d695e78463637b79464292e66c + - test-kind: + name: vm-1.24-kind + requires: [build] + kindNodeImage: kindest/node:v1.24.12@sha256:1e12918b8bc3d4253bc08f640a231bb0d3b2c5a9b28aa3f2ca1aee93e1e8db16 + # - test-kind: + # name: vm-1.25-kind + # requires: [build] + # kindNodeImage: kindest/node:v1.25.8@sha256:00d3f5314cc35327706776e95b2f8e504198ce59ac545d0200a89e69fce10b7f + - test-kind: + name: vm-1.26-kind + requires: [build] + kindNodeImage: kindest/node:v1.26.3@sha256:61b92f38dff6ccc29969e7aa154d34e38b89443af1a2c14e6cfbd2df6419c66f + - test-k3s: + name: vm-1.27-k3s + requires: [build] + # version v1.27.4+k3s1 fails with this issue https://github.com/moby/moby/issues/45935 + k3sVersion: v1.27.2+k3s1 + + - test-plugins: + <<: *only-internal-prs + requires: [build] + kindNodeImage: kindest/node:v1.21.14@sha256:27ef72ea623ee879a25fe6f9982690a3e370c68286f4356bf643467c552a3888 + + # This is only for edge release (Overrides version to edge-bonsai) + - build-dist: + <<: *only-main + name: build-dist-edge + version: edge-bonsai + requires: [build] + + - github-edge-prerelease: + <<: *only-main + version: edge-bonsai + requires: [build-dist-edge] + + - dockerhub-release: + <<: *only-main + context: docker + requires: + - build-dist-edge + - test-docker-gcloud: + context: docker + requires: [dockerhub-release] + tags: + jobs: + - build: + <<: *only-tags + - build-dist: + <<: *only-tags + requires: [build] + - dockerhub-release: + <<: *only-tags + context: docker + requires: [build-dist] + - github-release-tag: + <<: *only-tags + requires: [build-dist]