damondouglas commented on code in PR #24144: URL: https://github.com/apache/beam/pull/24144#discussion_r1035033138
########## playground/terraform/infrastructure/cloudbuild-manual-setup/README.md: ########## @@ -0,0 +1,156 @@ +<!--- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> + +# Beam Playground Cloud Build Setup + +This directory organizes Infrastructure-as-Code to provision dependent resources and set up Cloud Build for Beam Playground. Review Comment: There is no mention of this directory or README in [playground/terraform](https://github.com/akvelon/beam/blob/cloudbuild%2Bmanualsetup%2Bplayground/playground/terraform/README.md). Shouldn't the two instructions be integrated somehow? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/README.md: ########## @@ -0,0 +1,156 @@ +<!--- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> + +# Beam Playground Cloud Build Setup + +This directory organizes Infrastructure-as-Code to provision dependent resources and set up Cloud Build for Beam Playground. + +## Requirements: + +- [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects) +- [GCP User account](https://cloud.google.com/appengine/docs/standard/access-control?tab=python) _(Note: You will find the instruction "How to create User account" for your new project)_<br> + Ensure that the account has at least the following privileges: + - Service Account Admin + - Storage Admin + - Service Usage Admin + - Cloud Build Editor + - Security Admin + - Service Account User +- [gcloud CLI](https://cloud.google.com/sdk/docs/install-sdk) +- An existing GCP Bucket to save Terraform state - `state-bucket` +- DNS name for your Playground deployment instance +- [Terraform](https://www.terraform.io/) +- [Apache Beam GitHub](https://github.com/apache/beam) repository cloned locally + +## 1. Set up the Google Cloud Build for your GCP project + +The `playground/terraform/infrastructure/cloudbuild-manual-setup/01.setup` provisions dependencies required to set up Cloud Build for Playground: +- Required API services +- Cloud Build service account - `playground-cloudbuild-sa` +- IAM permissions for Cloud Build service account - `playground-cloudbuild-sa` + +#### To execute the module: + +1. Set following environment variables: Review Comment: Instead of relying on environment variables, could we defer to the standard terraform workflow of prompting a user of unset variables or overriding them? Modern IDE terraform plugins will autocomplete/prompt for required or optional variables when someone creates/edits a `.tfvars` file, such as `vars.tfvars` in the same directory as the module containing `variable "some_variable" {...}` blocks. The danger with extra documentation on environment variables is that now we've created two places that need to be kept in sync. When the module changes, someone needs to remember to update this documentation. Deferring to convention, allows us to prevent this coupling. We had to make the exception on [terraform/README.md#prepare-deployment-configuration](https://github.com/akvelon/beam/blob/cloudbuild%2Bmanualsetup%2Bplayground/playground/terraform/README.md#prepare-deployment-configuration) because we relied on this gradle wrapper. Now we have the opportunity to remove this coupling. The exception to this is perhaps `STATE_BUCKET`. ########## playground/terraform/infrastructure/cloudbuild-manual-setup/README.md: ########## @@ -0,0 +1,156 @@ +<!--- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> + +# Beam Playground Cloud Build Setup + +This directory organizes Infrastructure-as-Code to provision dependent resources and set up Cloud Build for Beam Playground. + +## Requirements: + +- [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects) +- [GCP User account](https://cloud.google.com/appengine/docs/standard/access-control?tab=python) _(Note: You will find the instruction "How to create User account" for your new project)_<br> + Ensure that the account has at least the following privileges: Review Comment: Replace `privileges` with [IAM roles](https://cloud.google.com/iam/docs/understanding-roles) ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/variables.tf: ########## @@ -0,0 +1,84 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +variable "project_id" { + type = string + description = "The ID of the Google Cloud project within which resources are provisioned" +} + +variable "region" { + type = string + description = "The Google Cloud Platform (GCP) region in which to provision resources" +} + +variable "infra_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground infrastructure" + default = "Playground-infrastructure-trigger" +} + +variable "gke_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground to GKE" + default = "Playground-to-gke-trigger" Review Comment: Can we user lower-case for all resource names? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/triggers.tf: ########## @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +data "google_service_account" "cloudbuild_sa" { + account_id = var.cloudbuild_service_account_id +} + +resource "google_cloudbuild_trigger" "playground_infrastructure" { + name = var.infra_trigger_name + location = var.region + project = var.project_id + + description = "Builds the base image and then runs cloud build config file to deploy Playground infrastructure" + + source_to_build { + uri = "https://github.com/apache/beam" Review Comment: Could we have a variable that defaults to the uri hardcoded here? What if someone needs to test their forked repository of beam? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/variables.tf: ########## @@ -0,0 +1,84 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +variable "project_id" { + type = string + description = "The ID of the Google Cloud project within which resources are provisioned" +} + +variable "region" { + type = string + description = "The Google Cloud Platform (GCP) region in which to provision resources" +} + +variable "infra_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground infrastructure" + default = "Playground-infrastructure-trigger" +} + +variable "gke_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground to GKE" + default = "Playground-to-gke-trigger" +} + +variable "cloudbuild_service_account_id" { + type = string + description = "The ID of the cloud build service account responsible for provisioning Google Cloud resources" + default = "playground-cloudbuild-sa" +} + +variable "playground_environment_name" { + description = "Environment where to deploy Playground. Located in playground/terraform/environment/{environment_name}" +} + +variable "playground_dns_name" { + description = "DNS record name for Playground website" +} + +variable "playground_network_name" { + description = "GCP VPC Network Name for Playground deployment" +} + +variable "playground_gke_name" { + description = "Playground GKE Cluster name" +} + +variable "state_bucket" { + description = "GCS bucket name for Beam Playground temp files and Terraform state" +} + +variable "image_tag" { + description = "The tag name for docker images of Playground containers" +} + +variable "docker_repository_root" { + description = "The name of GCP Artifact Registry Repository where Playground images will be saved to" +} + +variable "playground_region" { + description = "Region (us-central1) where playground infrastructure will be deployed" Review Comment: Does the region need to be in the same region as the artifact registry? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/variables.tf: ########## @@ -0,0 +1,84 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +variable "project_id" { + type = string + description = "The ID of the Google Cloud project within which resources are provisioned" +} + +variable "region" { + type = string + description = "The Google Cloud Platform (GCP) region in which to provision resources" +} + +variable "infra_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground infrastructure" + default = "Playground-infrastructure-trigger" +} + +variable "gke_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground to GKE" + default = "Playground-to-gke-trigger" +} + +variable "cloudbuild_service_account_id" { + type = string + description = "The ID of the cloud build service account responsible for provisioning Google Cloud resources" + default = "playground-cloudbuild-sa" +} + +variable "playground_environment_name" { + description = "Environment where to deploy Playground. Located in playground/terraform/environment/{environment_name}" Review Comment: Is `state.tfbackend` the only file needed in this directory? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/triggers.tf: ########## @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +data "google_service_account" "cloudbuild_sa" { + account_id = var.cloudbuild_service_account_id +} + +resource "google_cloudbuild_trigger" "playground_infrastructure" { + name = var.infra_trigger_name + location = var.region + project = var.project_id + + description = "Builds the base image and then runs cloud build config file to deploy Playground infrastructure" + + source_to_build { + uri = "https://github.com/apache/beam" + ref = "refs/heads/master" Review Comment: Could we have a variable that defaults to the ref hardcoded here? What if someone needs to test a branch? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/variables.tf: ########## @@ -0,0 +1,84 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +variable "project_id" { + type = string + description = "The ID of the Google Cloud project within which resources are provisioned" +} + +variable "region" { + type = string + description = "The Google Cloud Platform (GCP) region in which to provision resources" +} + +variable "infra_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground infrastructure" + default = "Playground-infrastructure-trigger" +} + +variable "gke_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground to GKE" + default = "Playground-to-gke-trigger" +} + +variable "cloudbuild_service_account_id" { + type = string + description = "The ID of the cloud build service account responsible for provisioning Google Cloud resources" + default = "playground-cloudbuild-sa" +} + +variable "playground_environment_name" { + description = "Environment where to deploy Playground. Located in playground/terraform/environment/{environment_name}" +} + +variable "playground_dns_name" { + description = "DNS record name for Playground website" +} + +variable "playground_network_name" { + description = "GCP VPC Network Name for Playground deployment" +} + +variable "playground_gke_name" { + description = "Playground GKE Cluster name" +} + +variable "state_bucket" { + description = "GCS bucket name for Beam Playground temp files and Terraform state" +} + +variable "image_tag" { + description = "The tag name for docker images of Playground containers" +} + +variable "docker_repository_root" { + description = "The name of GCP Artifact Registry Repository where Playground images will be saved to" +} + +variable "playground_region" { + description = "Region (us-central1) where playground infrastructure will be deployed" +} + +variable "playground_location" { + description = "Location (us-central1-b) where playground infrastructure will be deployed" Review Comment: Does `(us-central1-b` mean `(For example: us-central1-b)`? Instead of `location` could we say `zone`? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/triggers.tf: ########## @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +data "google_service_account" "cloudbuild_sa" { + account_id = var.cloudbuild_service_account_id +} + +resource "google_cloudbuild_trigger" "playground_infrastructure" { + name = var.infra_trigger_name + location = var.region + project = var.project_id + + description = "Builds the base image and then runs cloud build config file to deploy Playground infrastructure" + + source_to_build { Review Comment: Is it possible to do this instead? ``` github { owner = var.github_repository_owner name = var.github_repository_name push { branch = var.github_repository_branch } ``` ########## playground/terraform/infrastructure/cloudbuild-manual-setup/02.builders/variables.tf: ########## @@ -0,0 +1,84 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +variable "project_id" { + type = string + description = "The ID of the Google Cloud project within which resources are provisioned" +} + +variable "region" { + type = string + description = "The Google Cloud Platform (GCP) region in which to provision resources" +} + +variable "infra_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground infrastructure" + default = "Playground-infrastructure-trigger" +} + +variable "gke_trigger_name" { + type = string + description = "The name of the trigger that will deploy Playground to GKE" + default = "Playground-to-gke-trigger" +} + +variable "cloudbuild_service_account_id" { + type = string + description = "The ID of the cloud build service account responsible for provisioning Google Cloud resources" + default = "playground-cloudbuild-sa" +} + +variable "playground_environment_name" { + description = "Environment where to deploy Playground. Located in playground/terraform/environment/{environment_name}" +} + +variable "playground_dns_name" { + description = "DNS record name for Playground website" +} + +variable "playground_network_name" { + description = "GCP VPC Network Name for Playground deployment" +} + +variable "playground_gke_name" { + description = "Playground GKE Cluster name" +} + +variable "state_bucket" { + description = "GCS bucket name for Beam Playground temp files and Terraform state" +} + +variable "image_tag" { + description = "The tag name for docker images of Playground containers" +} + +variable "docker_repository_root" { + description = "The name of GCP Artifact Registry Repository where Playground images will be saved to" +} + +variable "playground_region" { + description = "Region (us-central1) where playground infrastructure will be deployed" Review Comment: Does `(us-central1)` mean `(For example: us-central1)`? ########## playground/terraform/infrastructure/cloudbuild-manual-setup/README.md: ########## @@ -0,0 +1,156 @@ +<!--- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> + +# Beam Playground Cloud Build Setup + +This directory organizes Infrastructure-as-Code to provision dependent resources and set up Cloud Build for Beam Playground. + +## Requirements: + +- [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects) +- [GCP User account](https://cloud.google.com/appengine/docs/standard/access-control?tab=python) _(Note: You will find the instruction "How to create User account" for your new project)_<br> + Ensure that the account has at least the following privileges: + - Service Account Admin + - Storage Admin + - Service Usage Admin + - Cloud Build Editor + - Security Admin + - Service Account User +- [gcloud CLI](https://cloud.google.com/sdk/docs/install-sdk) +- An existing GCP Bucket to save Terraform state - `state-bucket` +- DNS name for your Playground deployment instance +- [Terraform](https://www.terraform.io/) +- [Apache Beam GitHub](https://github.com/apache/beam) repository cloned locally + +## 1. Set up the Google Cloud Build for your GCP project + +The `playground/terraform/infrastructure/cloudbuild-manual-setup/01.setup` provisions dependencies required to set up Cloud Build for Playground: +- Required API services +- Cloud Build service account - `playground-cloudbuild-sa` +- IAM permissions for Cloud Build service account - `playground-cloudbuild-sa` + +#### To execute the module: + +1. Set following environment variables: + - `STATE_BUCKET`: GCP Storage bucket name to save Terraform state + - `GOOGLE_PROJECT`: GCP Project ID + - `GOOGLE_REGION`: GCP region to save triggers to + - `PLAYGROUND_REGION`: GCP Region (us-central1) where playground infrastructure will be deployed + - `PLAYGROUND_LOCATION`: GCP Location (us-central1-b) where playground infrastructure will be deployed + - `ENVIRONMENT_NAME`: Environment where Playground will be deployed (located at playground/terraform/environment/environment_name) + - `DNS_NAME`: DNS for deployed Playground webpage + - `NETWORK_NAME`: GCP VPC Network Name for Playground deployment + - `GKE_NAME`: Playground GKE Cluster name + - `TAG`: Tag for Playground images + - `SDK_TAG`: Tag for SDK images of Apache Beam Go and Python (typically last stable 2.42.0, 2.43.0) + - `DOCKER_REPOSITORY_ROOT`: GCP Artifact Registry repository name to store Playground container images + +```console + export STATE_BUCKET="state-bucket" \ + GOOGLE_PROJECT="project-id" \ + GOOGLE_REGION="us-central1" \ + PLAYGROUND_REGION="us-central1" \ + PLAYGROUND_LOCATION="us-central1-a" \ + ENVIRONMENT_NAME="env-name" \ + DNS_NAME="dns-name" \ + NETWORK_NAME="network-name" \ + GKE_NAME="gke-cluster-name" \ + TAG="tag-name" \ + SDK_TAG="2.43.0" + + export DOCKER_REPOSITORY_ROOT=\ + "$PLAYGROUND_REGION-docker.pkg.dev/$GOOGLE_PROJECT/playground-repository" +``` +**Note:** Please see [Cloud Build locations](https://cloud.google.com/build/docs/locations) for the list of all supported locations. + +2. Run commands: + + +```console +# Create a new authentication configuration for GCP Project with the created user account +gcloud init + +# Command imports new user account credentials into Application Default Credentials +gcloud auth application-default login + +# Navigate to 01.setup folder +cd playground/terraform/infrastructure/cloudbuild-manual-setup/01.setup/ + +# Run terraform scripts +terraform init -backend-config="bucket=$STATE_BUCKET" +terraform apply -var "project_id=$GOOGLE_PROJECT" Review Comment: `terraform apply -var="project_id=$(gcloud config get-value project)"` ########## playground/infrastructure/cloudbuild/env_init.sh: ########## @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +GO_VERSION=1.18 Review Comment: Should this be a variable defaulted to `1.18`? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
