transition from serverless framework to terraform

As outlined in the PR below, the latest version of the serverless framework is no longer free for large organizations.
https://github.com/rapidsai/ops-bot/pull/186
This PR provides a terraform-based implementation of the ops-bot deployment that Serverless Framework currently powers. It adds both terraform configs and a workflow that should support both PR and deployment workflows.

Terraform Plan 📝

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_api_gateway_authorizer.ops_bot will be created
  + resource "aws_api_gateway_authorizer" "ops_bot" {
      + arn                              = (known after apply)
      + authorizer_credentials           = (known after apply)
      + authorizer_result_ttl_in_seconds = 300
      + authorizer_uri                   = (known after apply)
      + id                               = (known after apply)
      + identity_source                  = "method.request.header.Authorization"
      + name                             = "ops-bot-authorizer"
      + rest_api_id                      = (known after apply)
      + type                             = "REQUEST"
    }

  # aws_api_gateway_deployment.ops_bot will be created
  + resource "aws_api_gateway_deployment" "ops_bot" {
      + created_date  = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + triggers      = (known after apply)
    }

  # aws_api_gateway_integration.lambda will be created
  + resource "aws_api_gateway_integration" "lambda" {
      + cache_namespace         = (known after apply)
      + connection_type         = "INTERNET"
      + http_method             = "POST"
      + id                      = (known after apply)
      + integration_http_method = "POST"
      + passthrough_behavior    = (known after apply)
      + resource_id             = (known after apply)
      + rest_api_id             = (known after apply)
      + timeout_milliseconds    = 29000
      + type                    = "AWS_PROXY"
      + uri                     = (known after apply)
    }

  # aws_api_gateway_method.proxy will be created
  + resource "aws_api_gateway_method" "proxy" {
      + api_key_required = false
      + authorization    = "CUSTOM"
      + authorizer_id    = (known after apply)
      + http_method      = "POST"
      + id               = (known after apply)
      + resource_id      = (known after apply)
      + rest_api_id      = (known after apply)
    }

  # aws_api_gateway_resource.proxy will be created
  + resource "aws_api_gateway_resource" "proxy" {
      + id          = (known after apply)
      + parent_id   = (known after apply)
      + path        = (known after apply)
      + path_part   = "{proxy+}"
      + rest_api_id = (known after apply)
    }

  # aws_api_gateway_rest_api.ops_bot will be created
  + resource "aws_api_gateway_rest_api" "ops_bot" {
      + api_key_source               = (known after apply)
      + arn                          = (known after apply)
      + binary_media_types           = (known after apply)
      + created_date                 = (known after apply)
      + description                  = (known after apply)
      + disable_execute_api_endpoint = (known after apply)
      + execution_arn                = (known after apply)
      + id                           = (known after apply)
      + minimum_compression_size     = (known after apply)
      + name                         = "ops-bot-prod"
      + policy                       = (known after apply)
      + root_resource_id             = (known after apply)
      + tags_all                     = (known after apply)

      + endpoint_configuration (known after apply)
    }

  # aws_api_gateway_stage.ops_bot will be created
  + resource "aws_api_gateway_stage" "ops_bot" {
      + arn           = (known after apply)
      + deployment_id = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + stage_name    = "prod"
      + tags_all      = (known after apply)
      + web_acl_arn   = (known after apply)
    }

  # aws_cloudwatch_log_group.authorizer will be created
  + resource "aws_cloudwatch_log_group" "authorizer" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-authorizerFn"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.probot_handler will be created
  + resource "aws_cloudwatch_log_group" "probot_handler" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-handleProbot"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_iam_role.api_gateway_authorizer will be created
  + resource "aws_iam_role" "api_gateway_authorizer" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "apigateway.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role.lambda_role will be created
  + resource "aws_iam_role" "lambda_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-lambda-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.api_gateway_authorizer will be created
  + resource "aws_iam_role_policy" "api_gateway_authorizer" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.lambda_policy will be created
  + resource "aws_iam_role_policy" "lambda_policy" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-lambda-policy"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_lambda_function.authorizer will be created
  + resource "aws_lambda_function" "authorizer" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-authorizerFn"
      + handler                        = "dist/authorizer.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "authorizer-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 3
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "probotFnName" = "ops-bot-prod-handleProbot"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

  # aws_lambda_function.probot_handler will be created
  + resource "aws_lambda_function" "probot_handler" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-handleProbot"
      + handler                        = "dist/probot.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "probot-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 900
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "APP_ID"         = (sensitive value)
              + "GPUTESTER_PAT"  = (sensitive value)
              + "LOG_FORMAT"     = "json"
              + "LOG_LEVEL"      = "debug"
              + "NODE_ENV"       = "prod"
              + "PRIVATE_KEY"    = (sensitive value)
              + "WEBHOOK_SECRET" = (sensitive value)
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

Plan: 15 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + api_gateway_url = (known after apply)

Terraform Plan 📝

Show Plan

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_api_gateway_authorizer.ops_bot will be created
  + resource "aws_api_gateway_authorizer" "ops_bot" {
      + arn                              = (known after apply)
      + authorizer_credentials           = (known after apply)
      + authorizer_result_ttl_in_seconds = 300
      + authorizer_uri                   = (known after apply)
      + id                               = (known after apply)
      + identity_source                  = "method.request.header.Authorization"
      + name                             = "ops-bot-authorizer"
      + rest_api_id                      = (known after apply)
      + type                             = "REQUEST"
    }

  # aws_api_gateway_deployment.ops_bot will be created
  + resource "aws_api_gateway_deployment" "ops_bot" {
      + created_date  = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + triggers      = (known after apply)
    }

  # aws_api_gateway_integration.lambda will be created
  + resource "aws_api_gateway_integration" "lambda" {
      + cache_namespace         = (known after apply)
      + connection_type         = "INTERNET"
      + http_method             = "POST"
      + id                      = (known after apply)
      + integration_http_method = "POST"
      + passthrough_behavior    = (known after apply)
      + resource_id             = (known after apply)
      + rest_api_id             = (known after apply)
      + timeout_milliseconds    = 29000
      + type                    = "AWS_PROXY"
      + uri                     = (known after apply)
    }

  # aws_api_gateway_method.proxy will be created
  + resource "aws_api_gateway_method" "proxy" {
      + api_key_required = false
      + authorization    = "CUSTOM"
      + authorizer_id    = (known after apply)
      + http_method      = "POST"
      + id               = (known after apply)
      + resource_id      = (known after apply)
      + rest_api_id      = (known after apply)
    }

  # aws_api_gateway_resource.proxy will be created
  + resource "aws_api_gateway_resource" "proxy" {
      + id          = (known after apply)
      + parent_id   = (known after apply)
      + path        = (known after apply)
      + path_part   = "{proxy+}"
      + rest_api_id = (known after apply)
    }

  # aws_api_gateway_rest_api.ops_bot will be created
  + resource "aws_api_gateway_rest_api" "ops_bot" {
      + api_key_source               = (known after apply)
      + arn                          = (known after apply)
      + binary_media_types           = (known after apply)
      + created_date                 = (known after apply)
      + description                  = (known after apply)
      + disable_execute_api_endpoint = (known after apply)
      + execution_arn                = (known after apply)
      + id                           = (known after apply)
      + minimum_compression_size     = (known after apply)
      + name                         = "ops-bot-prod"
      + policy                       = (known after apply)
      + root_resource_id             = (known after apply)
      + tags_all                     = (known after apply)

      + endpoint_configuration (known after apply)
    }

  # aws_api_gateway_stage.ops_bot will be created
  + resource "aws_api_gateway_stage" "ops_bot" {
      + arn           = (known after apply)
      + deployment_id = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + stage_name    = "prod"
      + tags_all      = (known after apply)
      + web_acl_arn   = (known after apply)
    }

  # aws_cloudwatch_log_group.authorizer will be created
  + resource "aws_cloudwatch_log_group" "authorizer" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-authorizerFn"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.probot_handler will be created
  + resource "aws_cloudwatch_log_group" "probot_handler" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-handleProbot"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_iam_role.api_gateway_authorizer will be created
  + resource "aws_iam_role" "api_gateway_authorizer" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "apigateway.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role.lambda_role will be created
  + resource "aws_iam_role" "lambda_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-lambda-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.api_gateway_authorizer will be created
  + resource "aws_iam_role_policy" "api_gateway_authorizer" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.lambda_policy will be created
  + resource "aws_iam_role_policy" "lambda_policy" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-lambda-policy"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_lambda_function.authorizer will be created
  + resource "aws_lambda_function" "authorizer" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-authorizerFn"
      + handler                        = "dist/authorizer.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "authorizer-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 3
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "probotFnName" = "ops-bot-prod-handleProbot"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

  # aws_lambda_function.probot_handler will be created
  + resource "aws_lambda_function" "probot_handler" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-handleProbot"
      + handler                        = "dist/probot.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "probot-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 900
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "APP_ID"         = (sensitive value)
              + "GPUTESTER_PAT"  = (sensitive value)
              + "LOG_FORMAT"     = "json"
              + "LOG_LEVEL"      = "debug"
              + "NODE_ENV"       = "prod"
              + "PRIVATE_KEY"    = (sensitive value)
              + "WEBHOOK_SECRET" = (sensitive value)
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

Plan: 15 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + api_gateway_url = (known after apply)

Terraform Plan 📝

Show Plan

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_api_gateway_authorizer.ops_bot will be created
  + resource "aws_api_gateway_authorizer" "ops_bot" {
      + arn                              = (known after apply)
      + authorizer_credentials           = (known after apply)
      + authorizer_result_ttl_in_seconds = 300
      + authorizer_uri                   = (known after apply)
      + id                               = (known after apply)
      + identity_source                  = "method.request.header.Authorization"
      + name                             = "ops-bot-authorizer"
      + rest_api_id                      = (known after apply)
      + type                             = "REQUEST"
    }

  # aws_api_gateway_deployment.ops_bot will be created
  + resource "aws_api_gateway_deployment" "ops_bot" {
      + created_date  = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + triggers      = (known after apply)
    }

  # aws_api_gateway_integration.lambda will be created
  + resource "aws_api_gateway_integration" "lambda" {
      + cache_namespace         = (known after apply)
      + connection_type         = "INTERNET"
      + http_method             = "POST"
      + id                      = (known after apply)
      + integration_http_method = "POST"
      + passthrough_behavior    = (known after apply)
      + resource_id             = (known after apply)
      + rest_api_id             = (known after apply)
      + timeout_milliseconds    = 29000
      + type                    = "AWS_PROXY"
      + uri                     = (known after apply)
    }

  # aws_api_gateway_method.proxy will be created
  + resource "aws_api_gateway_method" "proxy" {
      + api_key_required = false
      + authorization    = "CUSTOM"
      + authorizer_id    = (known after apply)
      + http_method      = "POST"
      + id               = (known after apply)
      + resource_id      = (known after apply)
      + rest_api_id      = (known after apply)
    }

  # aws_api_gateway_resource.proxy will be created
  + resource "aws_api_gateway_resource" "proxy" {
      + id          = (known after apply)
      + parent_id   = (known after apply)
      + path        = (known after apply)
      + path_part   = "{proxy+}"
      + rest_api_id = (known after apply)
    }

  # aws_api_gateway_rest_api.ops_bot will be created
  + resource "aws_api_gateway_rest_api" "ops_bot" {
      + api_key_source               = (known after apply)
      + arn                          = (known after apply)
      + binary_media_types           = (known after apply)
      + created_date                 = (known after apply)
      + description                  = (known after apply)
      + disable_execute_api_endpoint = (known after apply)
      + execution_arn                = (known after apply)
      + id                           = (known after apply)
      + minimum_compression_size     = (known after apply)
      + name                         = "ops-bot-prod"
      + policy                       = (known after apply)
      + root_resource_id             = (known after apply)
      + tags_all                     = (known after apply)

      + endpoint_configuration (known after apply)
    }

  # aws_api_gateway_stage.ops_bot will be created
  + resource "aws_api_gateway_stage" "ops_bot" {
      + arn           = (known after apply)
      + deployment_id = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + stage_name    = "prod"
      + tags_all      = (known after apply)
      + web_acl_arn   = (known after apply)
    }

  # aws_cloudwatch_log_group.authorizer will be created
  + resource "aws_cloudwatch_log_group" "authorizer" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-authorizerFn"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.probot_handler will be created
  + resource "aws_cloudwatch_log_group" "probot_handler" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-handleProbot"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_iam_role.api_gateway_authorizer will be created
  + resource "aws_iam_role" "api_gateway_authorizer" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "apigateway.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role.lambda_role will be created
  + resource "aws_iam_role" "lambda_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-lambda-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.api_gateway_authorizer will be created
  + resource "aws_iam_role_policy" "api_gateway_authorizer" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.lambda_policy will be created
  + resource "aws_iam_role_policy" "lambda_policy" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-lambda-policy"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_lambda_function.authorizer will be created
  + resource "aws_lambda_function" "authorizer" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-authorizerFn"
      + handler                        = "dist/authorizer.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "authorizer-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 3
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "probotFnName" = "ops-bot-prod-handleProbot"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

  # aws_lambda_function.probot_handler will be created
  + resource "aws_lambda_function" "probot_handler" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-handleProbot"
      + handler                        = "dist/probot.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "probot-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 900
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "APP_ID"         = (sensitive value)
              + "GPUTESTER_PAT"  = (sensitive value)
              + "LOG_FORMAT"     = "json"
              + "LOG_LEVEL"      = "debug"
              + "NODE_ENV"       = "prod"
              + "PRIVATE_KEY"    = (sensitive value)
              + "WEBHOOK_SECRET" = (sensitive value)
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

Plan: 15 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + api_gateway_url = (known after apply)

Terraform Plan 📝

Show Plan

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_api_gateway_authorizer.ops_bot will be created
  + resource "aws_api_gateway_authorizer" "ops_bot" {
      + arn                              = (known after apply)
      + authorizer_credentials           = (known after apply)
      + authorizer_result_ttl_in_seconds = 300
      + authorizer_uri                   = (known after apply)
      + id                               = (known after apply)
      + identity_source                  = "method.request.header.Authorization"
      + name                             = "ops-bot-authorizer"
      + rest_api_id                      = (known after apply)
      + type                             = "REQUEST"
    }

  # aws_api_gateway_deployment.ops_bot will be created
  + resource "aws_api_gateway_deployment" "ops_bot" {
      + created_date  = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + triggers      = (known after apply)
    }

  # aws_api_gateway_integration.lambda will be created
  + resource "aws_api_gateway_integration" "lambda" {
      + cache_namespace         = (known after apply)
      + connection_type         = "INTERNET"
      + http_method             = "POST"
      + id                      = (known after apply)
      + integration_http_method = "POST"
      + passthrough_behavior    = (known after apply)
      + resource_id             = (known after apply)
      + rest_api_id             = (known after apply)
      + timeout_milliseconds    = 29000
      + type                    = "AWS_PROXY"
      + uri                     = (known after apply)
    }

  # aws_api_gateway_method.proxy will be created
  + resource "aws_api_gateway_method" "proxy" {
      + api_key_required = false
      + authorization    = "CUSTOM"
      + authorizer_id    = (known after apply)
      + http_method      = "POST"
      + id               = (known after apply)
      + resource_id      = (known after apply)
      + rest_api_id      = (known after apply)
    }

  # aws_api_gateway_resource.proxy will be created
  + resource "aws_api_gateway_resource" "proxy" {
      + id          = (known after apply)
      + parent_id   = (known after apply)
      + path        = (known after apply)
      + path_part   = "{proxy+}"
      + rest_api_id = (known after apply)
    }

  # aws_api_gateway_rest_api.ops_bot will be created
  + resource "aws_api_gateway_rest_api" "ops_bot" {
      + api_key_source               = (known after apply)
      + arn                          = (known after apply)
      + binary_media_types           = (known after apply)
      + created_date                 = (known after apply)
      + description                  = (known after apply)
      + disable_execute_api_endpoint = (known after apply)
      + execution_arn                = (known after apply)
      + id                           = (known after apply)
      + minimum_compression_size     = (known after apply)
      + name                         = "ops-bot-prod"
      + policy                       = (known after apply)
      + root_resource_id             = (known after apply)
      + tags_all                     = (known after apply)

      + endpoint_configuration (known after apply)
    }

  # aws_api_gateway_stage.ops_bot will be created
  + resource "aws_api_gateway_stage" "ops_bot" {
      + arn           = (known after apply)
      + deployment_id = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + stage_name    = "prod"
      + tags_all      = (known after apply)
      + web_acl_arn   = (known after apply)
    }

  # aws_cloudwatch_log_group.authorizer will be created
  + resource "aws_cloudwatch_log_group" "authorizer" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-authorizerFn"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.probot_handler will be created
  + resource "aws_cloudwatch_log_group" "probot_handler" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-handleProbot"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_iam_role.api_gateway_authorizer will be created
  + resource "aws_iam_role" "api_gateway_authorizer" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "apigateway.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role.lambda_role will be created
  + resource "aws_iam_role" "lambda_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-lambda-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.api_gateway_authorizer will be created
  + resource "aws_iam_role_policy" "api_gateway_authorizer" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.lambda_policy will be created
  + resource "aws_iam_role_policy" "lambda_policy" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-lambda-policy"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_lambda_function.authorizer will be created
  + resource "aws_lambda_function" "authorizer" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-authorizerFn"
      + handler                        = "dist/authorizer.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "authorizer-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 3
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "probotFnName" = "ops-bot-prod-handleProbot"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

  # aws_lambda_function.probot_handler will be created
  + resource "aws_lambda_function" "probot_handler" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-handleProbot"
      + handler                        = "dist/probot.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "probot-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 900
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "APP_ID"         = (sensitive value)
              + "GPUTESTER_PAT"  = (sensitive value)
              + "LOG_FORMAT"     = "json"
              + "LOG_LEVEL"      = "debug"
              + "NODE_ENV"       = "prod"
              + "PRIVATE_KEY"    = (sensitive value)
              + "WEBHOOK_SECRET" = (sensitive value)
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

Plan: 15 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + api_gateway_url = (known after apply)

Documentation should be updated too

Terraform Plan 📝

Show Plan

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_api_gateway_authorizer.ops_bot will be created
  + resource "aws_api_gateway_authorizer" "ops_bot" {
      + arn                              = (known after apply)
      + authorizer_credentials           = (known after apply)
      + authorizer_result_ttl_in_seconds = 300
      + authorizer_uri                   = (known after apply)
      + id                               = (known after apply)
      + identity_source                  = "method.request.header.Authorization"
      + name                             = "ops-bot-authorizer"
      + rest_api_id                      = (known after apply)
      + type                             = "REQUEST"
    }

  # aws_api_gateway_deployment.ops_bot will be created
  + resource "aws_api_gateway_deployment" "ops_bot" {
      + created_date  = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + triggers      = (known after apply)
    }

  # aws_api_gateway_integration.lambda will be created
  + resource "aws_api_gateway_integration" "lambda" {
      + cache_namespace         = (known after apply)
      + connection_type         = "INTERNET"
      + http_method             = "POST"
      + id                      = (known after apply)
      + integration_http_method = "POST"
      + passthrough_behavior    = (known after apply)
      + resource_id             = (known after apply)
      + rest_api_id             = (known after apply)
      + timeout_milliseconds    = 29000
      + type                    = "AWS_PROXY"
      + uri                     = (known after apply)
    }

  # aws_api_gateway_method.proxy will be created
  + resource "aws_api_gateway_method" "proxy" {
      + api_key_required = false
      + authorization    = "CUSTOM"
      + authorizer_id    = (known after apply)
      + http_method      = "POST"
      + id               = (known after apply)
      + resource_id      = (known after apply)
      + rest_api_id      = (known after apply)
    }

  # aws_api_gateway_resource.proxy will be created
  + resource "aws_api_gateway_resource" "proxy" {
      + id          = (known after apply)
      + parent_id   = (known after apply)
      + path        = (known after apply)
      + path_part   = "{proxy+}"
      + rest_api_id = (known after apply)
    }

  # aws_api_gateway_rest_api.ops_bot will be created
  + resource "aws_api_gateway_rest_api" "ops_bot" {
      + api_key_source               = (known after apply)
      + arn                          = (known after apply)
      + binary_media_types           = (known after apply)
      + created_date                 = (known after apply)
      + description                  = (known after apply)
      + disable_execute_api_endpoint = (known after apply)
      + execution_arn                = (known after apply)
      + id                           = (known after apply)
      + minimum_compression_size     = (known after apply)
      + name                         = "ops-bot-prod"
      + policy                       = (known after apply)
      + root_resource_id             = (known after apply)
      + tags_all                     = (known after apply)

      + endpoint_configuration (known after apply)
    }

  # aws_api_gateway_stage.ops_bot will be created
  + resource "aws_api_gateway_stage" "ops_bot" {
      + arn           = (known after apply)
      + deployment_id = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + stage_name    = "prod"
      + tags_all      = (known after apply)
      + web_acl_arn   = (known after apply)
    }

  # aws_cloudwatch_log_group.authorizer will be created
  + resource "aws_cloudwatch_log_group" "authorizer" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-authorizerFn"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.probot_handler will be created
  + resource "aws_cloudwatch_log_group" "probot_handler" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-handleProbot"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_iam_role.api_gateway_authorizer will be created
  + resource "aws_iam_role" "api_gateway_authorizer" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "apigateway.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role.lambda_role will be created
  + resource "aws_iam_role" "lambda_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-lambda-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.api_gateway_authorizer will be created
  + resource "aws_iam_role_policy" "api_gateway_authorizer" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.lambda_policy will be created
  + resource "aws_iam_role_policy" "lambda_policy" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-lambda-policy"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_lambda_function.authorizer will be created
  + resource "aws_lambda_function" "authorizer" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-authorizerFn"
      + handler                        = "dist/authorizer.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "authorizer-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 3
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "probotFnName" = "ops-bot-prod-handleProbot"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

  # aws_lambda_function.probot_handler will be created
  + resource "aws_lambda_function" "probot_handler" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-handleProbot"
      + handler                        = "dist/probot.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "probot-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 900
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "APP_ID"         = (sensitive value)
              + "GPUTESTER_PAT"  = (sensitive value)
              + "LOG_FORMAT"     = "json"
              + "LOG_LEVEL"      = "debug"
              + "NODE_ENV"       = "prod"
              + "PRIVATE_KEY"    = (sensitive value)
              + "WEBHOOK_SECRET" = (sensitive value)
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

Plan: 15 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + api_gateway_url = (known after apply)

Terraform Plan 📝

Show Plan

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_api_gateway_authorizer.ops_bot will be created
  + resource "aws_api_gateway_authorizer" "ops_bot" {
      + arn                              = (known after apply)
      + authorizer_credentials           = (known after apply)
      + authorizer_result_ttl_in_seconds = 300
      + authorizer_uri                   = (known after apply)
      + id                               = (known after apply)
      + identity_source                  = "method.request.header.Authorization"
      + name                             = "ops-bot-authorizer"
      + rest_api_id                      = (known after apply)
      + type                             = "REQUEST"
    }

  # aws_api_gateway_deployment.ops_bot will be created
  + resource "aws_api_gateway_deployment" "ops_bot" {
      + created_date  = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + triggers      = (known after apply)
    }

  # aws_api_gateway_integration.lambda will be created
  + resource "aws_api_gateway_integration" "lambda" {
      + cache_namespace         = (known after apply)
      + connection_type         = "INTERNET"
      + http_method             = "POST"
      + id                      = (known after apply)
      + integration_http_method = "POST"
      + passthrough_behavior    = (known after apply)
      + resource_id             = (known after apply)
      + rest_api_id             = (known after apply)
      + timeout_milliseconds    = 29000
      + type                    = "AWS_PROXY"
      + uri                     = (known after apply)
    }

  # aws_api_gateway_method.proxy will be created
  + resource "aws_api_gateway_method" "proxy" {
      + api_key_required = false
      + authorization    = "CUSTOM"
      + authorizer_id    = (known after apply)
      + http_method      = "POST"
      + id               = (known after apply)
      + resource_id      = (known after apply)
      + rest_api_id      = (known after apply)
    }

  # aws_api_gateway_resource.proxy will be created
  + resource "aws_api_gateway_resource" "proxy" {
      + id          = (known after apply)
      + parent_id   = (known after apply)
      + path        = (known after apply)
      + path_part   = "{proxy+}"
      + rest_api_id = (known after apply)
    }

  # aws_api_gateway_rest_api.ops_bot will be created
  + resource "aws_api_gateway_rest_api" "ops_bot" {
      + api_key_source               = (known after apply)
      + arn                          = (known after apply)
      + binary_media_types           = (known after apply)
      + created_date                 = (known after apply)
      + description                  = (known after apply)
      + disable_execute_api_endpoint = (known after apply)
      + execution_arn                = (known after apply)
      + id                           = (known after apply)
      + minimum_compression_size     = (known after apply)
      + name                         = "ops-bot-prod"
      + policy                       = (known after apply)
      + root_resource_id             = (known after apply)
      + tags_all                     = (known after apply)

      + endpoint_configuration (known after apply)
    }

  # aws_api_gateway_stage.ops_bot will be created
  + resource "aws_api_gateway_stage" "ops_bot" {
      + arn           = (known after apply)
      + deployment_id = (known after apply)
      + execution_arn = (known after apply)
      + id            = (known after apply)
      + invoke_url    = (known after apply)
      + rest_api_id   = (known after apply)
      + stage_name    = "prod"
      + tags_all      = (known after apply)
      + web_acl_arn   = (known after apply)
    }

  # aws_cloudwatch_log_group.authorizer will be created
  + resource "aws_cloudwatch_log_group" "authorizer" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-authorizerFn"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.probot_handler will be created
  + resource "aws_cloudwatch_log_group" "probot_handler" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "/aws/lambda/ops-bot-prod-handleProbot"
      + name_prefix       = (known after apply)
      + retention_in_days = 60
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_iam_role.api_gateway_authorizer will be created
  + resource "aws_iam_role" "api_gateway_authorizer" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "apigateway.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role.lambda_role will be created
  + resource "aws_iam_role" "lambda_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = [
                          + "sts:AssumeRole",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                            ]
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ops-bot-prod-lambda-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.api_gateway_authorizer will be created
  + resource "aws_iam_role_policy" "api_gateway_authorizer" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-api-gateway-authorizer"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.lambda_policy will be created
  + resource "aws_iam_role_policy" "lambda_policy" {
      + id          = (known after apply)
      + name        = "ops-bot-prod-lambda-policy"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_lambda_function.authorizer will be created
  + resource "aws_lambda_function" "authorizer" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-authorizerFn"
      + handler                        = "dist/authorizer.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "authorizer-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 3
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "probotFnName" = "ops-bot-prod-handleProbot"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

  # aws_lambda_function.probot_handler will be created
  + resource "aws_lambda_function" "probot_handler" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "ops-bot-prod-handleProbot"
      + handler                        = "dist/probot.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 1024
      + package_type                   = "Zip"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs18.x"
      + s3_bucket                      = "rapidsai-serverless-deployments"
      + s3_key                         = "probot-.zip"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 900
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "APP_ID"         = (sensitive value)
              + "GPUTESTER_PAT"  = (sensitive value)
              + "LOG_FORMAT"     = "json"
              + "LOG_LEVEL"      = "debug"
              + "NODE_ENV"       = "prod"
              + "PRIVATE_KEY"    = (sensitive value)
              + "WEBHOOK_SECRET" = (sensitive value)
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config (known after apply)

      + tracing_config (known after apply)
    }

Plan: 15 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + api_gateway_url = (known after apply)

@raydouglass any final thoughts before I merge?
The deployment has been tested (via rapids-bot-testing app) with https://github.com/rapidsai/literate-octo-potato/pull/873.
Once this is merged and deployed, I will go ahead to switch the webhook endpoints here (and immediately test again).


Add a hidden option to authenticate scan queries

What

Add a hidden option to authenticate scan queries

That will be helpful to serve panels to moderators and admins (eg new Nutri-Score, or Data Quality Panel)

cc @stephanegigandet for Nutri-Score, cc @charlesnepote for the Data quality panel
        There is now an almost finished version on https://world.openfoodfacts.dev

The new Nutri-Score 2023 have not been recomputed on the dev server, so edit and save the product to see the changes.
@teolemon Note that the new panels are only served to admins, but it seems the app is not authenticating when reading products, so it doesn't get the new Nutri-Score panel.
Originally posted by @stephanegigandet in https://github.com/openfoodfacts/openfoodfacts-server/issues/9689#issuecomment-1912192274

@teolemon Generally speaking, would that mean systematically setting the app user parameter each time we query the server?
I've just had a look at the code and it looks like we systematically add the user to product-read server queries, except for single product refreshes (which are the most common, e.g. the refresh after product change).
In product_refresh.dart:
      final ProductResultV3 result = await OpenFoodAPIClient.getProductV3(
        getBarcodeQueryConfiguration(
          barcode,
          language,
        ),
        uriHelper: ProductQuery.uriProductHelper,
        // just add this parameter, that already exists -> user: ProductQuery.getUser(),
      );

That wouldn't be a hidden option, that would just be "From now on Smoothie always sends you the user, do whatever you want on the server side with that additional info".
Would only take 5 minutes to PR.

I'd like to get feedback on the monday Product Opener call before we move on that one.
There are privacy implications, and there are functional implications (how we want to do it).

@teolemon Let me summarize the current status.
If the user is logged in, we ALWAYS send the user in our server queries (READ/WRITE) except in one case: single product refresh (that we use all the time) where no user is provided.
Obviously we need to add the user parameter to the last remaining case (single product refresh), in order to match the needs from OP.
On the other hand, if it is considered as "inappropriate tracking", we should NOT use the user param in any READ server query when the user specified that no analytics should be performed. Assuming that using it for WRITE is tacit common sense.


Home page

Changes

Create initial home page
Fix race condition setting name of an object
Make logo background transparent
Simplify global styles
Make NavBar sticky on home page
Install classnames

Checklist

[x] Read the contribution guide and accept the code of conduct
[ ] Readme (updated or not needed)
[ ] Tests (added, updated or not needed)

📝Changed routes:

…...documentation-page]
/docs/docker/versions

(view full size)
(view full size)

/docs
/example

(view full size)
(view full size)

/

(view full size)

Commit 4a763dde600b67e91c93eebaa31d72d71f655e10 (https://website-aqr3flcwc-game-ci.vercel.app).

oh I just approved on commit actually, anyway, I did the same for ruby ahah. I went trough all docs pages and we don't have any other languages for now 👍

Cool. I'll merge this one then.

by the way for console I usually use bash instead.

Actually, console should be plaintext as we should not try to figure out bash commands out of text result from commands output. See #164 I'll see if there's a difference with no console vs plaintext.


Install hangs on Setting Up the Package Cache ...

I am attempting to install Miniconda 3 4.8.2, but the install hangs on setting up the package cache ... and does not progress no matter how long I leave it there.
I am installing on Windows 10 and running the install as an administrator.  Please let me know what other information you might need.
Thank you in advance for your help.

Hi Kurt - I suspect you're just trying to install Miniconda from Continuum.  This isn't an official repo for them - it's just a project I made (many years ago) that used Miniconda to install a bundled python app.  I would see if you could find help on https://www.anaconda.com/


Using custom decorators for controllers

Description
to re use code, I have created custom InternalError Decorators, that
I am aware that we have app.add_error_handler() function, but I was wondering if there was a way to wrap controller methods with decorators
Expected behaviour
Actual behaviour
Steps to reproduce
Additional info:
Output of the commands:

python --version 3.6
pip show connexion | grep "^Version\:" 2.6

Python decorators work as usual, so you can add a decorator with some wrapper logic to your handler function.


Limit number of pods of the same type in the same minion

Imagine a Kubernetes cluster with 10 minions where I start a Cassandra cluster with 10 nodes. It seems I'm not guaranteed that all nodes are scheduled evenly between the 10 minions. Can you confirm this behavior?
But even if it were, imagine for a moment that I'm using a nodeSelector that will choose from only 5 of the 10 minions. As a user, and depending on the application - in this case, it's still Cassandra - I'd like to have a way to define that kube should only schedule one Cassandra pod per node, so that in this case, Kube would prevent me from going with 10 Cassandra nodes in 5 minions (which would not make sense anyway, when thinking about HA and throughput).
Thoughts?
/cc @satnam6502

I vote @bgrant0607 for an answer. Thank you.

@pires We call what you are asking for "per-attribute limits". Please comment on #367 if this is a big concern for you. It's something we will likely add eventually, but it's not currently a high priority.
The scheduler currently spreads using labels on your pods. However, resource "requests" (cpu and memory in your container specs) are weighed equally with spreading, so you may not get even spreading, depending on whether any containers specify resource requirements. You can change the scheduler behavior pretty easily if you're building Kubernetes, and people are working on making it configurable.
Kubernetes doesn't currently do admission control based on whether your pods will schedule, since the apiserver accepts requests and the scheduler responds asynchronously. We do generate events in the case that they don't, however. We could discuss how we could surface this better, perhaps in a way that would facilitate a programmatic response. #1899 is likely part of the story.

@bgrant0607 thanks for the details.
So, if one defines a container (from now on, C) resource requests and provisions nodes with just what it needs for one C - not enough for 2 C -, the scheduler will guarantee that I have one C per node, right?
Regarding admission control and the async req/rsp between apiserver and scheduler couldn't one register one or more callbacks to when a response is received (future)? If such mechanism existed, it would be so easy to implement rules for dealing with such situation.

Yes, if you size your nodes and containers carefully, that would work.
We could potentially add a hook for the admission control, yes.

As a workaround, it is very acceptable. Thanks.

Just added a comment here https://github.com/GoogleCloudPlatform/kubernetes/issues/367#issuecomment-75620779

Jotting down an observation @bgrant0607 made last week about this issue: #9560 can be used to implement the feature requested here. For the Cassandra use case in the first entry in this issue, you'd label each Cassandra Pod with some label (for example, cassandra_node=true or whatever) and then specify cassandra_node=true as a conflict selector.
#9560 doesn't provide the full functionality of attribute limits -- namely, the limit can only be 1 not an arbitrary number, and it can only be used for excluding Pods from the host, not other from other pieces of the cluster topology (rack, power domain, or whatever). But it does let you do the equivalent of a Borg "hostname=1" attribute limit, which we found is the most commonly-used attribute limit at Google anyway.

Is this now possible? I'm looking at using kubernetes and would have a mixture of gpu minions and general purpose minions.  Two gpu containers can't share the gpu for resources.  These are dedicated 100% to a single app.

Is this now possible? I'm looking at using kubernetes and would have a mixture of gpu minions and general purpose minions.  Two gpu containers can't share the gpu for resources.  These are dedicated 100% to a single app.

We still don't have an explicit feature for this. However, the following should do what you want:

Set label "gpu=true" on the GPU minions, and label "gpu=false" on the non-GPU minions
Set selector "gpu=true" on the Pods that require GPU. If you want to keep the non-GPU Pods off of those machines, then set selector "gpu=false" on the non-GPU Pods.
On your GPU-requiring Pods set a containerPort (all of them should have the same containerPort value)

(1+2) will force the GPU-requiring Pods onto the GPU machines while (3) will prevent more than one from scheduling onto any single GPU machine (scheduler predicate for port conflict will fail after first GPU pod is scheduled onto a machine).

@davidopp - Thanks for that feedback.   I posted my example and question so people could see real-world scenarios that warrant the functionality.  Some of the answers in this thread from kubernetes developers seemed to hint that such functionality shouldn't be necessary.  But as you can see there are specific instances where it absolutely is.
Other things that can occur are that you have workloads that require specific GPU types that support cuda or opencl.  So I may have to get creative with labels and selectors.  Thanks for the feedback.

If you want to distribute one pod in per node, may be you can work just like [Collecting Docker Log Files with Fluentd and Elasticsearch] (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch/fluentd-es-image#collecting-docker-log-files-with-fluentd-and-elasticsearch), make the Cassandra start with kubelet, which would modify kubelet startup args like this --config=<your start config file or dir>. Maybe you can find some idea in this blog.

I think #18265 will do what you want.

For the Cassandra use case in the first entry in this issue, you'd label each Cassandra Pod with some label (for example, cassandra_node=true or whatever) and then specify cassandra_node=true as a conflict selector.

@davidopp can you clarify what you mean by conflict selector? is this a current feature or should I just be following progress on affinity?

I actually have no idea what I meant with that comment. The way to get a guarantee of no more than one pod per node today is to set a hostPort in your pod template, so that every replica will get the same hostPort and thus the scheduler won't put more than one replica on a node (since only one pod can take the same host port on a node). We will have a principled method of specifying this once pod affinity is implemented -- it should be in HEAD within a month, but won't be in an official release until 1.3.

@davidopp Thanks I've been writing a blog post with replicated databases in containers similar to sandeep's here https://medium.com/google-cloud/mongodb-replica-sets-with-kubernetes-d96606bd9474
looking forward to 1.3

Oh and the design doc for it is here
https://github.com/kubernetes/kubernetes/blob/master/docs/design/podaffinity.md

@davidopp It works just fine until a container in the pod dies and the kubernetes pause container remains.
I have a issue with setting the hostport on my spec where if a container in the pod fails this container still remains preventing the pod from restarting.
docker ps yields
cab9460a414d        gcr.io/google_containers/pause:0.8.0        "/pause"                 5 minutes ago
 Up 5 minutes        <IP_ADDRESS>:4000->27017/tcp   k8s_POD.1aab01fe_mongo-1-wcm8x_default_de2328e7-e1ab-11e5-9b9f-0e9ab77c0fc1_eb748490

When I inspect the pod
 9s	9s	1	{kubelet ip-10-0-0-57.ec2.internal}	implicitly required container POD	Failed	Failed to start with docker id 8803208e9585 with error: API error (500): Cannot start container

8803208e958529239dd809b15a08e044bdd7206279d9df5f78c650f4fce01d6c: failed to create endpoint k8s_POD.1aab01fe_mongo-1-wcm8x_default_de2328e7-e1ab-11e5-9b9f-0e9ab77c0fc1_749ef47c on network bridge:
 Bind for <IP_ADDRESS>:4000 failed: port is already allocated

@Stephenitis Just to be clear, the pause container should be running in a separate podJust to make sure I understand, what you're doing is:

Start your pod. It has (how many?) containers in it. At least one of them (say container C) has a containerPort.hostPort.
C fails
C can't restart because of a port conflict wit the pause pod?

But it seems the output you gave shows the pause pod is the one that can't start, not your pod?
cc/ @bprashanth

sorry I wasn't detailed enough with my earlier post. The pod that is failing is my mongo pod. The pause container is persisting and preventing the mongo pod from starting.
1m		1m		1	{kubelet ip-10-0-0-99.ec2.internal}	implicitly required container POD	Failed		Failed to start with docker id 2cc69a9becca with error: API error (500): Cannot start container 2cc69a9becca2479e76d89305f3f2117e3d5b979910e5f5f93fc339eeecb1442: failed to create endpoint k8s_POD.1aab01fe_mongo-1-axf6w_default_50e66af4-e437-11e5-9f0c-0e9b63fce83d_333cc975 on network bridge: Bind for <IP_ADDRESS>:4000 failed: port is already allocated

#	Copyright 2016, Google, Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
kind: ReplicationController
apiVersion: v1
metadata:
  name: mongo-1
spec:
  replicas: 1
  selector:
    name: mongo-node-1
    role: mongo
    environment: test
  template:
    spec:
      containers:
        - name: mongo-node-1
          image: mongo
          command:
            - mongod
            - "--replSet"
            - rs0
            - "--smallfiles"
            - "--noprealloc"
          ports:
            - containerPort: 27017
              hostPort: 4000
          volumeMounts:
            - name: mongo-persistent-storage
              mountPath: /data/db
        - name: mongo-sidecar
          image: leportlabs/mongo-k8s-sidecar
          env:
            - name: MONGO_SIDECAR_POD_LABELS
              value: "role=mongo,environment=test"
      volumes:
        - name: mongo-persistent-storage
          flocker:
            datasetName: flockermongorc-1
    metadata:
      labels:
        name: mongo-node-1
        role: mongo
        environment: test

Closing this one, this is essentially inter-pod anti-affinity.
/cc @rrati


Is it possible to add additional locales?

It seems (correct me if I'm wrong) that Twitter-cldr currently only includes the same locales that are available on twitter.com.
Is it somehow possible to add support for other locales that are available in the CLDR as well? Perhaps  when building?

@camertron and what about the wiki page? as @ragulka I want to add some more additional languages

@FDiskas Ok. The steps have probably changed a bit since I initially wrote my response in 2012. There's also some work that needs to be done to bring twitter-cldr-js up to speed with updates to twitter-cldr-rb that I haven't had time to tackle.
If you want, you can try following the steps above to add the new locales you're interested in. If you run into issues, let me know.

I checked http://cldr.unicode.org/ and there is a lithuanian language but missing here in repository.
Please provide any steps how to import or convert  the language from http://cldr.unicode.org to twitter-cldr-js
Thanks

@FDiskas @ragulka I have improved and added to the available rake tasks in twitter-cldr-rb, so adding new languages should be easy now (i.e. bundle exec rake add_locale[lt]). However, twitter-cldr-js needs some significant work to bring it up to speed with the data provided by the ruby version. I haven't had time to do this work yet, but it's definitely on my radar.


Fix some spelling/grammar mistakes in Chapter 0

I'm currently working through the textbook (it's really awesome, btw!)
While reading through it, i fixed some typos/grammar "on the go".
I've made a commit for each change with a commit-message, so there is some more context for discussions.

 Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.


the codebase design has high coupling and need to be refactored

The advantage is that the algorithm in the project is very rich, and the disadvantage is that the code coupling of the entire project is too high and there is no modular design in fact.
The disadvantage of high coupling is that few users can really use some of the functions or class, if you really hope users use the library you create, refactot it.
Think and learn why libraries with high quality design, e.g. pytorch, hugging face,  success.

Thanks for your comments. Do you have any detailed suggestions for us to improve further, such as some specific modules or functions?

hi @PaParaZz1, thank for your response. my personal suggestion are as follows, just for reference.
background
the DI-engine combines so many different functionalities into one library, e.g. env or its wrappers, buffer, algorithms, training process et al, which results in high coupling and low readability and resusability. It seems work well as a whole, but the single module has low generalization and few users can really use this library, even it is hard to use some of the functions or class in their research pipeline.
suggestions
Just like hugging face does, we should split the whole project into different libraries where every single library has only one main research purpose, following the Single Responsibility Principle.

rl model library and its pretrained params.  like the positioning of hugging face transformer library.
a general rl trainging framework. Corresponding to hugging face accelerate library positioning.
a general Experience Buffer library, handling priority/non-priority, sequence/none-sequence experience. just like tokenizer positioning.
a model-base rl library, handling model-based case. just like pytorch-image-models, diffusers positioning.

et al.

Thanks for your suggestions, we are planning to separate reward model and world model parts for different sub domains. For the design of replay buffer, we have already refactored this part with new storage and middleware design, you can refer to this doc. For pretrained parameters, we are working on Hugging Face + DI-engine Model Zoo, you can refer to here for more details.