From b9d2353596c3914e53252d42608dc7dae6cd0e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 29 Aug 2024 02:01:28 +0200 Subject: [PATCH] generator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .github/workflows/test.yml | 902 ++++++++++++++++++++++++++--- .gitignore | 1 + hack/chainsaw-matrix/go.mod | 2 +- hack/chainsaw-matrix/main.go | 82 ++- hack/chainsaw-matrix/workflow.yaml | 56 ++ 5 files changed, 950 insertions(+), 93 deletions(-) create mode 100644 hack/chainsaw-matrix/workflow.yaml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 72faaa9c5..4f652b8ba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,3 +1,5 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + name: E2E Tests permissions: {} @@ -13,72 +15,834 @@ concurrency: cancel-in-progress: true jobs: - chainsaw: - strategy: - fail-fast: false - matrix: - k8s-version: - - name: v1.28 - version: v1.28.13 - - name: v1.29 - version: v1.29.8 - - name: v1.30 - version: v1.30.4 - - name: v1.31 - version: v1.31.0 - tests: - - ^argo$/^(application-field-validation|application-prevent-default-project|application-prevent-updates-project|applicationset-name-matches-project|appproject-clusterresourceblacklist|argo-cluster-generation-from-rancher-capi)$ - - ^aws$/^(require-encryption-aws-loadbalancers)$ - - ^best-practices$/^(add-network-policy|add-networkpolicy-dns|add-ns-quota|add-rolebinding|add-safe-to-evict|disallow-cri-sock-mount|disallow-default-namespace|disallow-empty-ingress-host|disallow-helm-tiller|disallow-latest-tag|require-drop-all|require-drop-cap-net-raw|require-labels)$ - - ^best-practices$/^(require-pod-requests-limits|require-probes|require-ro-rootfs|restrict-image-registries|restrict-node-port|restrict-service-external-ips)$ - - ^castai$/^(add-castai-removal-disabled)$ - - ^cert-manager$/^(limit-dnsnames|limit-duration|restrict-issuer)$ - - ^cleanup$/^(cleanup-bare-pods|cleanup-empty-replicasets)$ - - ^consul$/^(enforce-min-tls-version)$ - - ^external-secret-operator$/^(add-external-secret-prefix)$ - - ^flux$/^(generate-flux-multi-tenant-resources|verify-flux-images|verify-flux-sources|verify-git-repositories)$ - - ^istio$/^(add-ambient-mode-namespace|add-sidecar-injection-namespace|create-authorizationpolicy|enforce-ambient-mode-namespace|enforce-sidecar-injection-namespace|enforce-strict-mtls|enforce-tls-hosts-host-subnets|prevent-disabling-injection-pods|require-authorizationpolicy|restrict-virtual-service-wildcard|service-mesh-disallow-capabilities|service-mesh-require-run-as-nonroot)$ - - ^karpenter$/^(add-karpenter-daemonset-priority-class|add-karpenter-donot-evict|add-karpenter-nodeselector|set-karpenter-non-cpu-limits)$ - - ^kasten$/^(kasten-3-2-1-backup|kasten-data-protection-by-label|kasten-generate-policy-by-preset-label|kasten-hourly-rpo|kasten-minimum-retention|kasten-validate-ns-by-preset-label)$ - - ^kubecost$/^(enable-kubecost-continuous-rightsizing|require-kubecost-labels)$ - - ^kubeops$/^(config-syncer-secret-generation-from-rancher-capi)$ - - ^kubevirt$/^(add-services|enforce-instancetype)$ - - ^linkerd$/^(add-linkerd-mesh-injection|add-linkerd-policy-annotation|check-linkerd-authorizationpolicy|prevent-linkerd-pod-injection-override|prevent-linkerd-port-skipping|require-linkerd-mesh-injection|require-linkerd-server)$ - - ^nginx-ingress$/^(disallow-ingress-nginx-custom-snippets|restrict-annotations|restrict-ingress-paths)$ - - ^openshift$/^(check-routes|disallow-security-context-constraint-anyuid|disallow-self-provisioner-binding)$ - - ^other$/^(add-certificates-volume|add-default-resources|add-default-securitycontext|add-emptydir-sizelimit|add-env-vars-from-cm|add-image-as-env-var|add-imagepullsecrets|add-imagepullsecrets-for-containers-and-initcontainers|add-labels|add-ndots|add-node-affinity|add-node-labels-pod|add-nodeSelector)$ - - ^other$/^(add-pod-priorityclassname|add-pod-proxies|add-tolerations|add-ttl-jobs|add-volume-deployment|advanced-restrict-image-registries|allowed-annotations|allowed-base-images|allowed-image-repos|allowed-label-changes|allowed-pod-priorities|always-pull-images|annotate-base-images)$ - - ^other$/^(apply-pss-restricted-profile|audit-event-on-delete|audit-event-on-exec|block-cluster-admin-from-ns|block-ephemeral-containers|block-images-with-volumes|block-large-images|block-pod-exec-by-namespace|block-pod-exec-by-namespace-label|block-pod-exec-by-pod-and-container|block-pod-exec-by-pod-label|block-pod-exec-by-pod-name|block-stale-images)$ - - ^other$/^(block-updates-deletes|check-env-vars|check-hpa-exists|check-nvidia-gpu|check-serviceaccount|check-serviceaccount-secrets|check-subjectaccessreview|check-vpa-configuration|concatenate-configmaps|copy-namespace-labels|create-default-pdb|create-pod-antiaffinity|deny-commands-in-exec-probe)$ - - ^other$/^(deny-secret-service-account-token-type|deployment-replicas-higher-than-pdb|disable-automountserviceaccounttoken|disable-service-discovery|disallow-all-secrets|disallow-localhost-services|disallow-secrets-from-env-vars|dns-policy-and-dns-config|docker-socket-requires-label|enforce-pod-duration|enforce-resources-as-ratio|ensure-probes-different|ensure-production-matches-staging)$ - - ^other$/^(ensure-readonly-hostpath|exclude-namespaces-dynamically|forbid-cpu-limits|generate-networkpolicy-existing|get-debug-information|imagepullpolicy-always|ingress-host-match-tls|inject-env-var-from-image-label|inject-sidecar-deployment|inspect-csr|kubernetes-version-check|label-existing-namespaces|label-nodes-cri)$ - - ^other$/^(limit-configmap-for-sa|limit-containers-per-pod|limit-hostpath-type-pv|limit-hostpath-vols|memory-requests-equal-limits|metadata-match-regex|mitigate-log4shell|mutate-large-termination-gps|mutate-pod-binding|namespace-inventory-check|nfs-subdir-external-provisioner-storage-path|only-trustworthy-registries-set-root|pdb-maxunavailable)$ - - ^other$/^(pdb-maxunavailable-with-deployments|pdb-minavailable|policy-for-exceptions|prepend-image-registry|prevent-bare-pods|prevent-cr8escape|prevent-duplicate-hpa|prevent-duplicate-vpa|protect-node-taints|record-creation-details|refresh-env-var-in-pod|refresh-volumes-in-pods|remove-hostpath-volumes)$ - - ^other$/^(remove-serviceaccount-token|replace-image-registry|replace-image-registry-with-harbor|replace-ingress-hosts|require-annotations|require-base-image|require-container-port-names|require-cpu-limits|require-deployments-have-multiple-replicas|require-emptydir-requests-limits|require-image-checksum|require-image-source|require-imagepullsecrets)$ - - ^other$/^(require-ingress-https|require-netpol|require-non-root-groups|require-pdb|require-pod-priorityclassname|require-qos-burstable|require-qos-guaranteed|require-reasonable-pdbs|require-replicas-allow-disruption|require-storageclass|require-unique-external-dns|require-unique-service-selector|require-unique-uid-per-workload)$ - - ^other$/^(resolve-image-to-digest|resource-creation-updating-denied|restart-deployment-on-secret-change|restrict-annotations|restrict-automount-sa-token|restrict-binding-clusteradmin|restrict-binding-system-groups|restrict-clusterrole-csr|restrict-clusterrole-mutating-validating-admission-webhooks|restrict-clusterrole-nodesproxy|restrict-controlplane-scheduling|restrict-deprecated-registry|restrict-escalation-verbs-roles)$ - - ^other$/^(restrict-ingress-classes|restrict-ingress-defaultbackend|restrict-ingress-host|restrict-ingress-wildcard|restrict-jobs|restrict-loadbalancer|restrict-networkpolicy-empty-podselector|restrict-node-affinity|restrict-node-label-changes|restrict-node-label-creation|restrict-node-selection|restrict-pod-controller-serviceaccount-updates|restrict-sa-automount-sa-token)$ - - ^other$/^(restrict-secret-role-verbs|restrict-secrets-by-label|restrict-secrets-by-name|restrict-service-port-range|restrict-storageclass|restrict-usergroup-fsgroup-id|restrict-wildcard-resources|restrict-wildcard-verbs|scale-deployment-zero|spread-pods-across-topology|sync-secrets|topologyspreadconstraints-policy|unique-ingress-host-and-path)$ - - ^other$/^(unique-ingress-paths|update-image-tag|verify-vpa-target)$ - - ^pod-security$/^baseline$/^(disallow-capabilities|disallow-host-namespaces|disallow-host-path|disallow-host-ports|disallow-host-ports-range|disallow-host-process|disallow-privileged-containers|disallow-proc-mount|disallow-selinux|restrict-apparmor-profiles|restrict-seccomp|restrict-sysctls)$ - - ^pod-security$/^restricted$/^(disallow-capabilities-strict|disallow-privilege-escalation|require-run-as-non-root-user|require-run-as-nonroot|restrict-seccomp-strict|restrict-volume-types)$ - - ^pod-security$/^subrule$/^restricted$/^(restricted-exclude-capabilities|restricted-exclude-seccomp|restricted-latest)$ - - ^psa$/^(add-privileged-existing-namespaces|add-psa-labels|add-psa-namespace-reporting|deny-privileged-profile)$ - - ^psp-migration$/^(add-apparmor|add-capabilities|add-runtimeClassName|check-supplemental-groups|restrict-adding-capabilities|restrict-runtimeClassName)$ - - ^tekton$/^(block-tekton-task-runs|require-tekton-bundle|require-tekton-namespace-pipelinerun)$ - - ^traefik$/^(disallow-default-tlsoptions)$ - - ^velero$/^(backup-all-volumes|block-velero-restore|validate-cron-schedule)$ - - ^windows-security$/^(require-run-as-containeruser)$ - runs-on: ubuntu-latest - name: ${{ matrix.k8s-version.name }} - ${{ matrix.tests }} - steps: - - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Setup Environment - uses: ./.github/actions/setup-env - with: - k8s-version: ${{ matrix.k8s-version.version }} - - name: Run Tests - uses: ./.github/actions/run-tests - with: - tests: ${{ matrix.tests }} + argo: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^argo$/^(application-field-validation|application-prevent-default-project|application-prevent-updates-project|applicationset-name-matches-project|appproject-clusterresourceblacklist|argo-cluster-generation-from-rancher-capi)$ + aws: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^aws$/^(require-encryption-aws-loadbalancers)$ + best-practices: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^best-practices$/^(add-network-policy|add-networkpolicy-dns|add-ns-quota|add-rolebinding|add-safe-to-evict|disallow-cri-sock-mount|disallow-default-namespace|disallow-empty-ingress-host|disallow-helm-tiller|disallow-latest-tag|require-drop-all|require-drop-cap-net-raw)$ + best-practices-12: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^best-practices$/^(require-labels|require-pod-requests-limits|require-probes|require-ro-rootfs|restrict-image-registries|restrict-node-port|restrict-service-external-ips)$ + castai: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^castai$/^(add-castai-removal-disabled)$ + cert-manager: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^cert-manager$/^(limit-dnsnames|limit-duration|restrict-issuer)$ + cleanup: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^cleanup$/^(cleanup-bare-pods|cleanup-empty-replicasets)$ + consul: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^consul$/^(enforce-min-tls-version)$ + external-secret-operator: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^external-secret-operator$/^(add-external-secret-prefix)$ + flux: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^flux$/^(generate-flux-multi-tenant-resources|verify-flux-images|verify-flux-sources|verify-git-repositories)$ + istio: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^istio$/^(add-ambient-mode-namespace|add-sidecar-injection-namespace|create-authorizationpolicy|enforce-ambient-mode-namespace|enforce-sidecar-injection-namespace|enforce-strict-mtls|enforce-tls-hosts-host-subnets|prevent-disabling-injection-pods|require-authorizationpolicy|restrict-virtual-service-wildcard|service-mesh-disallow-capabilities|service-mesh-require-run-as-nonroot)$ + karpenter: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^karpenter$/^(add-karpenter-daemonset-priority-class|add-karpenter-donot-evict|add-karpenter-nodeselector|set-karpenter-non-cpu-limits)$ + kasten: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^kasten$/^(kasten-3-2-1-backup|kasten-data-protection-by-label|kasten-generate-policy-by-preset-label|kasten-hourly-rpo|kasten-minimum-retention|kasten-validate-ns-by-preset-label)$ + kubecost: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^kubecost$/^(enable-kubecost-continuous-rightsizing|require-kubecost-labels)$ + kubeops: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^kubeops$/^(config-syncer-secret-generation-from-rancher-capi)$ + kubevirt: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^kubevirt$/^(add-services|enforce-instancetype)$ + linkerd: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^linkerd$/^(add-linkerd-mesh-injection|add-linkerd-policy-annotation|check-linkerd-authorizationpolicy|prevent-linkerd-pod-injection-override|prevent-linkerd-port-skipping|require-linkerd-mesh-injection|require-linkerd-server)$ + nginx-ingress: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^nginx-ingress$/^(disallow-ingress-nginx-custom-snippets|restrict-annotations|restrict-ingress-paths)$ + openshift: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^openshift$/^(check-routes|disallow-security-context-constraint-anyuid|disallow-self-provisioner-binding)$ + other: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(add-certificates-volume|add-default-resources|add-default-securitycontext|add-emptydir-sizelimit|add-env-vars-from-cm|add-image-as-env-var|add-imagepullsecrets|add-imagepullsecrets-for-containers-and-initcontainers|add-labels|add-ndots|add-node-affinity|add-node-labels-pod)$ + other-12: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(add-nodeSelector|add-pod-priorityclassname|add-pod-proxies|add-tolerations|add-ttl-jobs|add-volume-deployment|advanced-restrict-image-registries|allowed-annotations|allowed-base-images|allowed-image-repos|allowed-label-changes|allowed-pod-priorities)$ + other-24: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(always-pull-images|annotate-base-images|apply-pss-restricted-profile|audit-event-on-delete|audit-event-on-exec|block-cluster-admin-from-ns|block-ephemeral-containers|block-images-with-volumes|block-large-images|block-pod-exec-by-namespace|block-pod-exec-by-namespace-label|block-pod-exec-by-pod-and-container)$ + other-36: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(block-pod-exec-by-pod-label|block-pod-exec-by-pod-name|block-stale-images|block-updates-deletes|check-env-vars|check-hpa-exists|check-nvidia-gpu|check-serviceaccount|check-serviceaccount-secrets|check-subjectaccessreview|check-vpa-configuration|concatenate-configmaps)$ + other-48: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(copy-namespace-labels|create-default-pdb|create-pod-antiaffinity|deny-commands-in-exec-probe|deny-secret-service-account-token-type|deployment-replicas-higher-than-pdb|disable-automountserviceaccounttoken|disable-service-discovery|disallow-all-secrets|disallow-localhost-services|disallow-secrets-from-env-vars|dns-policy-and-dns-config)$ + other-60: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(docker-socket-requires-label|enforce-pod-duration|enforce-resources-as-ratio|ensure-probes-different|ensure-production-matches-staging|ensure-readonly-hostpath|exclude-namespaces-dynamically|forbid-cpu-limits|generate-networkpolicy-existing|get-debug-information|imagepullpolicy-always|ingress-host-match-tls)$ + other-72: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(inject-env-var-from-image-label|inject-sidecar-deployment|inspect-csr|kubernetes-version-check|label-existing-namespaces|label-nodes-cri|limit-configmap-for-sa|limit-containers-per-pod|limit-hostpath-type-pv|limit-hostpath-vols|memory-requests-equal-limits|metadata-match-regex)$ + other-84: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(mitigate-log4shell|mutate-large-termination-gps|mutate-pod-binding|namespace-inventory-check|nfs-subdir-external-provisioner-storage-path|only-trustworthy-registries-set-root|pdb-maxunavailable|pdb-maxunavailable-with-deployments|pdb-minavailable|policy-for-exceptions|prepend-image-registry|prevent-bare-pods)$ + other-96: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(prevent-cr8escape|prevent-duplicate-hpa|prevent-duplicate-vpa|protect-node-taints|record-creation-details|refresh-env-var-in-pod|refresh-volumes-in-pods|remove-hostpath-volumes|remove-serviceaccount-token|replace-image-registry|replace-image-registry-with-harbor|replace-ingress-hosts)$ + other-108: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(require-annotations|require-base-image|require-container-port-names|require-cpu-limits|require-deployments-have-multiple-replicas|require-emptydir-requests-limits|require-image-checksum|require-image-source|require-imagepullsecrets|require-ingress-https|require-netpol|require-non-root-groups)$ + other-120: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(require-pdb|require-pod-priorityclassname|require-qos-burstable|require-qos-guaranteed|require-reasonable-pdbs|require-replicas-allow-disruption|require-storageclass|require-unique-external-dns|require-unique-service-selector|require-unique-uid-per-workload|resolve-image-to-digest|resource-creation-updating-denied)$ + other-132: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(restart-deployment-on-secret-change|restrict-annotations|restrict-automount-sa-token|restrict-binding-clusteradmin|restrict-binding-system-groups|restrict-clusterrole-csr|restrict-clusterrole-mutating-validating-admission-webhooks|restrict-clusterrole-nodesproxy|restrict-controlplane-scheduling|restrict-deprecated-registry|restrict-escalation-verbs-roles|restrict-ingress-classes)$ + other-144: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(restrict-ingress-defaultbackend|restrict-ingress-host|restrict-ingress-wildcard|restrict-jobs|restrict-loadbalancer|restrict-networkpolicy-empty-podselector|restrict-node-affinity|restrict-node-label-changes|restrict-node-label-creation|restrict-node-selection|restrict-pod-controller-serviceaccount-updates|restrict-sa-automount-sa-token)$ + other-156: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(restrict-secret-role-verbs|restrict-secrets-by-label|restrict-secrets-by-name|restrict-service-port-range|restrict-storageclass|restrict-usergroup-fsgroup-id|restrict-wildcard-resources|restrict-wildcard-verbs|scale-deployment-zero|spread-pods-across-topology|sync-secrets|topologyspreadconstraints-policy)$ + other-168: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^other$/^(unique-ingress-host-and-path|unique-ingress-paths|update-image-tag|verify-vpa-target)$ + pod-security_baseline: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^pod-security$/^baseline$/^(disallow-capabilities|disallow-host-namespaces|disallow-host-path|disallow-host-ports|disallow-host-ports-range|disallow-host-process|disallow-privileged-containers|disallow-proc-mount|disallow-selinux|restrict-apparmor-profiles|restrict-seccomp|restrict-sysctls)$ + pod-security_restricted: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^pod-security$/^restricted$/^(disallow-capabilities-strict|disallow-privilege-escalation|require-run-as-non-root-user|require-run-as-nonroot|restrict-seccomp-strict|restrict-volume-types)$ + pod-security_subrule_restricted: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^pod-security$/^subrule$/^restricted$/^(restricted-exclude-capabilities|restricted-exclude-seccomp|restricted-latest)$ + psa: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^psa$/^(add-privileged-existing-namespaces|add-psa-labels|add-psa-namespace-reporting|deny-privileged-profile)$ + psp-migration: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^psp-migration$/^(add-apparmor|add-capabilities|add-runtimeClassName|check-supplemental-groups|restrict-adding-capabilities|restrict-runtimeClassName)$ + tekton: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^tekton$/^(block-tekton-task-runs|require-tekton-bundle|require-tekton-namespace-pipelinerun)$ + traefik: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^traefik$/^(disallow-default-tlsoptions)$ + velero: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^velero$/^(backup-all-volumes|block-velero-restore|validate-cron-schedule)$ + windows-security: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: ${{ matrix.k8s-version }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: ^windows-security$/^(require-run-as-containeruser)$ + e2e-required-success: + name: e2e-required + needs: + - argo + - aws + - best-practices + - best-practices-12 + - castai + - cert-manager + - cleanup + - consul + - external-secret-operator + - flux + - istio + - karpenter + - kasten + - kubecost + - kubeops + - kubevirt + - linkerd + - nginx-ingress + - openshift + - other + - other-12 + - other-24 + - other-36 + - other-48 + - other-60 + - other-72 + - other-84 + - other-96 + - other-108 + - other-120 + - other-132 + - other-144 + - other-156 + - other-168 + - pod-security_baseline + - pod-security_restricted + - pod-security_subrule_restricted + - psa + - psp-migration + - tekton + - traefik + - velero + - windows-security + runs-on: ubuntu-latest + if: ${{ success() }} + steps: + - run: ${{ true }} + e2e-required-failure: + name: e2e-required + needs: + - argo + - aws + - best-practices + - best-practices-12 + - castai + - cert-manager + - cleanup + - consul + - external-secret-operator + - flux + - istio + - karpenter + - kasten + - kubecost + - kubeops + - kubevirt + - linkerd + - nginx-ingress + - openshift + - other + - other-12 + - other-24 + - other-36 + - other-48 + - other-60 + - other-72 + - other-84 + - other-96 + - other-108 + - other-120 + - other-132 + - other-144 + - other-156 + - other-168 + - pod-security_baseline + - pod-security_restricted + - pod-security_subrule_restricted + - psa + - psp-migration + - tekton + - traefik + - velero + - windows-security + runs-on: ubuntu-latest + if: ${{ failure() || cancelled() }} + steps: + - run: ${{ false }} diff --git a/.gitignore b/.gitignore index 5da35b529..e357231e5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ settings.json .idea .DS_Store kubeconfig +hack/chainsaw-matrix/chainsaw-matrix diff --git a/hack/chainsaw-matrix/go.mod b/hack/chainsaw-matrix/go.mod index ddb82d553..10ae32083 100644 --- a/hack/chainsaw-matrix/go.mod +++ b/hack/chainsaw-matrix/go.mod @@ -1,6 +1,6 @@ module github.com/kyverno/policies/hack/chainsaw-matrix -go 1.22.2 +go 1.23.0 require github.com/kyverno/chainsaw v0.2.8 diff --git a/hack/chainsaw-matrix/main.go b/hack/chainsaw-matrix/main.go index c75f6f29d..5f62d1ab3 100644 --- a/hack/chainsaw-matrix/main.go +++ b/hack/chainsaw-matrix/main.go @@ -2,14 +2,32 @@ package main import ( "fmt" + "maps" + "os" "path/filepath" "slices" "strings" + "text/template" "github.com/kyverno/chainsaw/pkg/discovery" ) -const max = 12 +const chunkSize = 12 + +type testSuite struct { + Name string + Pattern string + Folder string + Required bool +} + +type values struct { + TestSuites []testSuite +} + +type payload struct { + Values values +} func main() { tests, err := discovery.DiscoverTests("chainsaw-test.yaml", nil, false, "../..") @@ -32,30 +50,48 @@ func main() { parts = parts[:len(parts)-1] paths = append(paths, strings.Join(parts, "/")) } - slices.Sort(paths) - root := "" - var entries []string - flush := func() { - if len(entries) != 0 { - pattern := "" - for _, part := range strings.Split(root, "/") { - pattern += "^" + part + "$" + "/" - } - pattern += "^" + "(" + strings.Join(entries, "|") + ")" + "$" - fmt.Println("- " + pattern) - entries = nil - } - } + suites := map[string][]string{} for _, path := range paths { parts := strings.Split(path, "/") - parent := strings.Join(parts[:len(parts)-1], "/") - if parent != root { - flush() - } else if len(entries) > max { - flush() + root := strings.Join(parts[:len(parts)-1], "/") + suites[root] = append(suites[root], parts[len(parts)-1]) + } + var ts []testSuite + for _, key := range slices.Sorted(maps.Keys(suites)) { + root := "" + for _, part := range strings.Split(key, "/") { + root += "^" + part + "$" + "/" } - root = parent - entries = append(entries, parts[len(parts)-1]) + slices.Sort(suites[key]) + for i := 0; i < len(suites[key]); i += chunkSize { + end := i + chunkSize + if end > len(suites[key]) { + end = len(suites[key]) + } + pattern := root + "^" + "(" + strings.Join(suites[key][i:end], "|") + ")" + "$" + name := strings.ReplaceAll(key, "/", "_") + if i >= chunkSize { + name = fmt.Sprintf("%s-%d", name, i) + } + ts = append(ts, testSuite{ + Required: true, + Name: name, + Folder: key, + Pattern: pattern, + }) + } + } + var tmplFile = "workflow.yaml" + tmpl, err := template.New(tmplFile).ParseFiles(tmplFile) + if err != nil { + panic(err) + } + err = tmpl.Execute(os.Stdout, payload{ + Values: values{ + TestSuites: ts, + }, + }) + if err != nil { + panic(err) } - flush() } diff --git a/hack/chainsaw-matrix/workflow.yaml b/hack/chainsaw-matrix/workflow.yaml new file mode 100644 index 000000000..215ee7da8 --- /dev/null +++ b/hack/chainsaw-matrix/workflow.yaml @@ -0,0 +1,56 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + +name: E2E Tests + +permissions: {} + +on: + workflow_dispatch: {} + pull_request: + branches: + - 'main' + +concurrency: + group: {{ print "${{ github.workflow }}-${{ github.ref }}" }} + cancel-in-progress: true + +jobs: + {{- range .Values.TestSuites }} + {{ .Name }}: + strategy: + fail-fast: false + matrix: + k8s-version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Environment + uses: ./.github/actions/setup-env + with: + k8s-version: {{ print "${{ matrix.k8s-version }}" }} + - name: Run Tests + uses: ./.github/actions/run-tests + with: + tests: {{ .Pattern }} + {{- end }} + e2e-required-success: + name: e2e-required + needs: + {{- range .Values.TestSuites }} + - {{ .Name }} + {{- end }} + runs-on: ubuntu-latest + if: {{ print "${{ success() }}" }} + steps: + - run: {{ print "${{ true }}" }} + e2e-required-failure: + name: e2e-required + needs: + {{- range .Values.TestSuites }} + - {{ .Name }} + {{- end }} + runs-on: ubuntu-latest + if: {{ print "${{ failure() || cancelled() }}" }} + steps: + - run: {{ print "${{ false }}" }}