Source code for which_runtime.impl

# -*- coding: utf-8 -*-

"""
Runtime refers to the specific computational environment in which your code
is executed. For example, running code on a local laptop, CI/CD build environments,
AWS EC2 instances, AWS Lambda functions, and more. Understanding the current runtime
is essential as it can impact how your code behaves.

For instance, when running your code on a local laptop, you might want to use
an AWS CLI named profile to access DevOps or workload AWS accounts. However,
in an application runtime like AWS Lambda, the default Boto session is typically
preconfigured for the current workload AWS account.

This Python module is designed to detect the current runtime information and
offers a set of ``is_xyz`` methods to assist you in crafting conditional logic
for performing different actions based on the runtime. Notably, many of these
methods employ the LAZY LOAD technique for efficiency.
"""

import os
import sys
import enum
from functools import cached_property

USER_RUNTIME_NAME = "USER_RUNTIME_NAME"


[docs] class RunTimeGroupEnum(str, enum.Enum): """ Enumeration of common runtime groups in AWS projects. """ local = "local" ci = "ci" app = "app" unknown = "unknown"
[docs] class RunTimeEnum(str, enum.Enum): """ Enumeration of common runtime in AWS projects. """ # local runtime group local = "local" aws_cloud9 = "aws_cloud9" # ci runtime group aws_codebuild = "aws_codebuild" github_action = "github_action" gitlab_ci = "gitlab_ci" bitbucket_pipeline = "bitbucket_pipeline" circleci = "circleci" jenkins = "jenkins" # app runtime group aws_lambda = "aws_lambda" aws_batch = "aws_batch" aws_glue = "aws_glue" aws_ec2 = "aws_ec2" aws_ecs = "aws_ecs" vercel = "vercel" # special runtimes glue_container = "glue_container" unknown = "unknown"
runtime_emoji_mapper = { RunTimeEnum.local: "💻", RunTimeEnum.aws_cloud9: "💻", RunTimeEnum.aws_codebuild: "🏗", RunTimeEnum.github_action: "🏗", RunTimeEnum.gitlab_ci: "🏗", RunTimeEnum.bitbucket_pipeline: "🏗", RunTimeEnum.circleci: "🏗", RunTimeEnum.jenkins: "🏗", RunTimeEnum.aws_lambda: "🚀", RunTimeEnum.aws_batch: "🚀", RunTimeEnum.aws_glue: "🚀", RunTimeEnum.aws_ec2: "🚀", RunTimeEnum.aws_ecs: "🚀", RunTimeEnum.glue_container: "🗳", RunTimeEnum.unknown: "🤔", } def _check_user_env_var(expect: str) -> bool: """ Users can manually set the runtime using the ``USER_RUNTIME_NAME`` environment variable to override the default detection rules. """ return os.environ.get(USER_RUNTIME_NAME, "__unknown") == expect
[docs] class Runtime: """ Detect the current runtime information by inspecting environment variables. The instance of this class is the entry point of all kinds of runtime related variables, methods. You can extend this class to add more runtime detection logic. """ # -------------------------------------------------------------------------- # detect if it is a specific runtime # -------------------------------------------------------------------------- @cached_property def is_aws_codebuild(self) -> bool: """ AWS CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces software packages ready for deployment. It eliminates the need to provision, manage, and scale your own build servers. Detection is primarily based on the presence of the ``CODEBUILD_BUILD_ID`` environment variable, which is automatically set in the AWS CodeBuild build environment. Reference: - https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html """ if _check_user_env_var(RunTimeEnum.aws_codebuild.value): # pragma: no cover return True return "CODEBUILD_BUILD_ID" in os.environ @cached_property def is_github_action(self) -> bool: """ GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. It enables developers to create workflows that build and test every pull request to your repository. Detection relies on the presence of the ``GITHUB_ACTION`` environment variable, which is automatically set in GitHub Actions runner environments. Reference: - https://docs.github.com/en/actions/learn-github-actions/variables """ if _check_user_env_var(RunTimeEnum.github_action.value): # pragma: no cover return True return "GITHUB_ACTION" in os.environ @cached_property def is_gitlab_ci(self) -> bool: """ Reference: - https://docs.gitlab.com/ee/ci/variables/predefined_variables.html """ if _check_user_env_var(RunTimeEnum.gitlab_ci.value): # pragma: no cover return True return "CI_PROJECT_ID" in os.environ @cached_property def is_bitbucket_pipeline(self) -> bool: """ Bitbucket Pipelines is a continuous integration and continuous delivery (CI/CD) service built into Bitbucket Cloud. It allows developers to automatically build, test, and deploy their code based on a configuration file in their repository. Detection relies on the presence of the ``BITBUCKET_BUILD_NUMBER`` environment variable, which is automatically set in Bitbucket Pipeline environments. Reference: - https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/ """ if _check_user_env_var( RunTimeEnum.bitbucket_pipeline.value ): # pragma: no cover return True return "BITBUCKET_BUILD_NUMBER" in os.environ @cached_property def is_circleci(self) -> bool: """ CircleCI is a cloud-based continuous integration and continuous delivery (CI/CD) platform that automates the software development process, from code building to testing and deployment. Detection is based on the presence of the ``CIRCLECI`` environment variable, which is automatically set in CircleCI runner environments. Reference: - https://circleci.com/docs/variables/ """ if _check_user_env_var(RunTimeEnum.circleci.value): # pragma: no cover return True return "CIRCLECI" in os.environ @cached_property def is_jenkins(self) -> bool: """ Jenkins is an open-source automation server that supports building, deploying, and automating any software development project through continuous integration and continuous delivery (CI/CD). Detection relies on the presence of both ``BUILD_TAG`` and ``EXECUTOR_NUMBER`` environment variables, which are typically set in Jenkins build environments. Reference: - https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables """ if _check_user_env_var(RunTimeEnum.jenkins.value): # pragma: no cover return True return "BUILD_TAG" in os.environ and "EXECUTOR_NUMBER" in os.environ @cached_property def is_aws_lambda(self) -> bool: """ AWS Lambda is a serverless compute service that lets you run code without provisioning or managing servers. It supports various programming languages and automatically scales your application by running code in response to each trigger. Detection is based on the presence of the ``AWS_LAMBDA_FUNCTION_NAME`` environment variable, which is automatically set in AWS Lambda function execution environments. Reference: - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html """ if _check_user_env_var(RunTimeEnum.aws_lambda.value): # pragma: no cover return True return "AWS_LAMBDA_FUNCTION_NAME" in os.environ @cached_property def is_aws_batch(self) -> bool: """ AWS Batch is a fully managed batch computing service that enables developers to easily and efficiently run hundreds of thousands of batch computing jobs on AWS. It dynamically provisions optimal quantity and type of compute resources based on job requirements. Detection relies on the presence of the ``AWS_BATCH_JOB_ID`` environment variable, which is automatically set in AWS Batch job environments. Reference: - https://docs.aws.amazon.com/batch/latest/userguide/job_env_vars.html """ if _check_user_env_var(RunTimeEnum.aws_batch.value): # pragma: no cover return True return "AWS_BATCH_JOB_ID" in os.environ @cached_property def is_aws_glue(self) -> bool: """ AWS Glue is a fully managed extract, transform, and load (ETL) service that makes it easy to prepare and load data for analytics. It automatically provisions and manages the resources required for data transformation and movement. Detection is based on the presence of the ``--JOB_RUN_ID`` argument in system arguments, which is typically used in AWS Glue job environments. """ if _check_user_env_var(RunTimeEnum.aws_glue.value): # pragma: no cover return True return "--JOB_RUN_ID" in sys.argv @cached_property def is_aws_cloud9(self) -> bool: """ AWS Cloud9 is a cloud-based integrated development environment (IDE) that lets you write, run, and debug code with just a web browser. It provides a complete development environment in the cloud, including a code editor, debugger, and terminal. Detection relies on the presence of the ``C9`` environment variable, which can be manually set in Cloud9 environments. Note that this method may not be stable. You can add the ``export C9=true`` to the ``~/.bashrc`` or ``~/.bash_profile`` to make it stable. Reference: - https://docs.aws.amazon.com/cloud9/latest/user-guide/env-vars.html """ if _check_user_env_var(RunTimeEnum.aws_cloud9.value): # pragma: no cover return True return "C9" in os.environ @cached_property def is_aws_ec2(self) -> bool: """ Amazon EC2 (Elastic Compute Cloud) provides scalable computing capacity in the AWS cloud. It allows users to run virtual servers, known as instances, with various configurations and operating systems. Detection is based on a custom ``IS_AWS_EC2`` environment variable, as there's no standard built-in way to detect EC2 instances. You should set a custom environment variable for your ec2 instances to make it stable. """ if _check_user_env_var(RunTimeEnum.aws_ec2.value): # pragma: no cover return True return "IS_AWS_EC2" in os.environ @cached_property def is_aws_ecs(self) -> bool: """ Amazon ECS (Elastic Container Service) is a fully managed container orchestration service that helps you easily deploy, manage, and scale containerized applications using Docker containers. Detection relies on a custom ``IS_AWS_ECS_TASK`` environment variable, as there's no standard built-in way to detect ECS task containers. You could set a custom environment variable for your ECS task to make it stable. Reference: - https://docs.aws.amazon.com/AmazonECS/latest/userguide/taskdef-envfiles.html """ if _check_user_env_var(RunTimeEnum.aws_ecs.value): # pragma: no cover return True return "IS_AWS_ECS_TASK" in os.environ @cached_property def is_glue_container(self) -> bool: """ Glue container runtime refers to the specific environment used for running AWS Glue ETL jobs in a containerized setting. This provides additional flexibility in job execution and resource management. Detection is based on a custom ``IS_GLUE_CONTAINER`` environment variable set to 'true', as there's no standard built-in way to detect Glue containers. You could set a custom environment variable for your Glue container to make it stable. """ if _check_user_env_var(RunTimeEnum.aws_ecs.value): # pragma: no cover return True return os.environ.get("IS_GLUE_CONTAINER", "false") == "true" @cached_property def is_vercel(self) -> bool: if _check_user_env_var(RunTimeEnum.vercel.value): # pragma: no cover return True return os.environ.get("VERCEL", "NOTHING") == "1" @cached_property def is_local(self) -> bool: """ Local runtime represents a standard development environment on a personal computer or local workstation. It is the default runtime when no specific cloud or CI/CD environment is detected. Detection occurs by checking if none of the other specific runtime environments are active. Users can also manually set the runtime using the USER_RUNTIME_NAME environment variable to explicitly indicate a local runtime. """ if _check_user_env_var(RunTimeEnum.local.value): # pragma: no cover return True # or is a short-circuit operator, the performance is good flag = ( self.is_aws_codebuild or self.is_github_action or self.is_gitlab_ci or self.is_bitbucket_pipeline or self.is_circleci or self.is_jenkins or self.is_aws_lambda or self.is_aws_batch or self.is_aws_glue or self.is_aws_cloud9 or self.is_aws_ec2 or self.is_aws_ecs or self.is_glue_container or self.is_vercel ) return not flag @cached_property def current_runtime(self) -> str: # pragma: no cover """ Return the human friendly name of the current runtime. """ if os.environ.get(USER_RUNTIME_NAME, "__unknown") != "__unknown": return os.environ[USER_RUNTIME_NAME] if self.is_aws_codebuild: return RunTimeEnum.aws_codebuild.value if self.is_github_action: return RunTimeEnum.github_action.value if self.is_gitlab_ci: return RunTimeEnum.gitlab_ci.value if self.is_bitbucket_pipeline: return RunTimeEnum.bitbucket_pipeline.value if self.is_circleci: return RunTimeEnum.circleci.value if self.is_jenkins: return RunTimeEnum.jenkins.value if self.is_aws_lambda: return RunTimeEnum.aws_lambda.value if self.is_aws_batch: return RunTimeEnum.aws_batch.value if self.is_aws_glue: return RunTimeEnum.aws_glue.value if self.is_aws_cloud9: return RunTimeEnum.aws_cloud9.value if self.is_aws_ec2: return RunTimeEnum.aws_ec2.value if self.is_aws_ecs: return RunTimeEnum.aws_ecs.value if self.is_glue_container: return RunTimeEnum.glue_container.value if self.is_vercel: return RunTimeEnum.vercel.value if self.is_local: return RunTimeEnum.local.value return RunTimeEnum.unknown.value # -------------------------------------------------------------------------- # detect if it is a specific runtime group # -------------------------------------------------------------------------- @cached_property def is_local_runtime_group(self) -> bool: """ Local runtime group encompasses development environments where a developer has direct access to the local file system and operating system. This includes standard local machines and cloud-based development environments like AWS Cloud9. Detection is based on checking if the current runtime is either a local machine or an AWS Cloud9 environment. """ return self.is_local or self.is_aws_cloud9 @cached_property def is_ci_runtime_group(self) -> bool: # pragma: no cover """ CI (Continuous Integration) runtime group includes various automated build and testing environments used in software development workflows. These are platforms that automatically build, test, and validate code changes. Detection checks for the presence of any CI platform environment variables (CodeBuild, GitHub Actions, GitLab CI, etc.) or a generic 'CI' environment variable. """ if ( self.is_aws_codebuild or self.is_github_action or self.is_gitlab_ci or self.is_bitbucket_pipeline or self.is_circleci or self.is_jenkins ): return True else: return "CI" in os.environ @cached_property def is_app_runtime_group(self) -> bool: """ Application runtime group includes cloud-based execution environments where application code is deployed and run. This covers various serverless and container-based platforms for running production applications. Detection checks if the current runtime is any of the supported application platforms like AWS Lambda, Batch, Glue, EC2, ECS, or Cloud9. """ return ( self.is_aws_lambda or self.is_aws_batch or self.is_aws_glue or self.is_aws_cloud9 or self.is_aws_ec2 or self.is_aws_ecs ) @cached_property def current_runtime_group(self) -> str: # pragma: no cover """ Return the human friendly name of the current runtime group. """ if self.is_ci_runtime_group: return RunTimeGroupEnum.ci.value if self.is_app_runtime_group: return RunTimeGroupEnum.app.value if self.is_local_runtime_group: return RunTimeGroupEnum.local.value return RunTimeGroupEnum.unknown.value
# A singleton object that can be used in your concrete project. runtime = Runtime()