""" Module used for detecting whether SAMCLI is executed in a CI/CD environment. """ import os from enum import Enum, auto from typing import Callable, Dict, Mapping, Optional, Union class CICDPlatform(Enum): Jenkins = auto() GitLab = auto() GitHubAction = auto() TravisCI = auto() CircleCI = auto() AWSCodeBuild = auto() TeamCity = auto() Bamboo = auto() Buddy = auto() CodeShip = auto() Semaphore = auto() Appveyor = auto() # make sure Unknown is at the bottom, it is the fallback. Other = auto() def _is_codeship(environ: Mapping) -> bool: """ Use environ to determine whether it is running in CodeShip. According to the doc, https://docs.cloudbees.com/docs/cloudbees-codeship/latest/basic-builds-and-configuration/set-environment-variables > CI_NAME # Always CodeShip. Ex: codeship to handle both "CodeShip" and "codeship," here the string is converted to lower case first. Parameters ---------- environ Returns ------- bool whether the env is CodeShip """ ci_name: str = environ.get("CI_NAME", "").lower() return ci_name == "codeship" def _is_jenkins(environ: Mapping) -> bool: """ Use environ to determine whether it is running in Jenkins. According to the doc, https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#working-with-your-jenkinsfile > BUILD_TAG > String of jenkins-${JOB_NAME}-${BUILD_NUMBER}. > ... > JENKINS_URL > Full URL of Jenkins, such as https://example.com:port/jenkins/ > (NOTE: only available if Jenkins URL set in "System Configuration") Here firstly check JENKINS_URL's presence, if not, then fallback to check BUILD_TAG starts with "jenkins" """ return "JENKINS_URL" in environ or environ.get("BUILD_TAG", "").startswith("jenkins-") _ENV_VAR_OR_CALLABLE_BY_PLATFORM: Dict[CICDPlatform, Union[str, Callable[[Mapping], bool]]] = { CICDPlatform.Jenkins: _is_jenkins, # https://docs.gitlab.com/ee/ci/variables/predefined_variables.html CICDPlatform.GitLab: "GITLAB_CI", # https://docs.github.com/en/actions/reference/environment-variables CICDPlatform.GitHubAction: "GITHUB_ACTION", # https://docs.travis-ci.com/user/environment-variables/ CICDPlatform.TravisCI: "TRAVIS", # https://circleci.com/docs/2.0/env-vars/ CICDPlatform.CircleCI: "CIRCLECI", # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html CICDPlatform.AWSCodeBuild: "CODEBUILD_BUILD_ID", # https://www.jetbrains.com/help/teamcity/predefined-build-parameters.html CICDPlatform.TeamCity: "TEAMCITY_VERSION", # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html CICDPlatform.Bamboo: "bamboo_buildNumber", # https://buddy.works/docs/pipelines/environment-variables CICDPlatform.Buddy: "BUDDY", CICDPlatform.CodeShip: _is_codeship, # https://docs.semaphoreci.com/ci-cd-environment/environment-variables/ CICDPlatform.Semaphore: "SEMAPHORE", # https://www.appveyor.com/docs/environment-variables/ CICDPlatform.Appveyor: "APPVEYOR", CICDPlatform.Other: "CI", } def _is_cicd_platform(cicd_platform: CICDPlatform, environ: Mapping) -> bool: """ Check whether sam-cli run in a particular CI/CD platform based on certain environment variables. Parameters ---------- cicd_platform an enum CICDPlatform object indicating which CI/CD platform to check against. environ the mapping to look for environment variables, for example, os.environ. Returns ------- bool A boolean indicating whether there are environment variables matching the cicd_platform. """ env_var_or_callable = _ENV_VAR_OR_CALLABLE_BY_PLATFORM[cicd_platform] if isinstance(env_var_or_callable, str): return env_var_or_callable in environ # it is a callable, use the return value return env_var_or_callable(environ) class CICDDetector: _cicd_platform: Optional[CICDPlatform] def __init__(self): try: self._cicd_platform: Optional[CICDPlatform] = next( cicd_platform for cicd_platform in CICDPlatform if _is_cicd_platform(cicd_platform, os.environ) ) except StopIteration: self._cicd_platform = None def platform(self) -> Optional[CICDPlatform]: """ Identify which CICD platform SAM CLI is running in. Returns ------- CICDPlatform an optional CICDPlatform enum indicating the CICD platform. """ return self._cicd_platform