# Generate Log Index for External Developers

We use a Cloud Run deployment to generate an `index.html` GCS object listing all
the logs for each PR, ore specifically, each commit SHA in each PR. This GCS
object is posted on a bucket with public read access, and referenced from
comments in the PR so contributors can find it.

This document describes the steps necessary to set up this Cloud Run deployment.
The main audience is `google-cloud-cpp` team members that need to update the
deployment. You are expected to be familiar with Docker, and Google Cloud
Platform, particularly with Cloud Run and GCS.

## Prerequisites

Verify the [docker tool][docker] is functional on your workstation:

```shell
docker run hello-world
# Output: Hello from Docker! and then some more informational messages.
```

Verify the [pack tool][pack-install] is functional on our workstation. These
instructions were tested with `v0.17.0`, although they should work with newer
versions. Some commands may not work with older versions.

```shell
pack version
# Output: a version number, e.g., 0.17.0+git-d9cb4e7.build-2045
```

## Enable Writing on the Destination Bucket

Note: These commands only needs to be run once. They are here in case we ever
move the build to a different project.

The Cloud Run deployment needs to write to the destination bucket. The
deployment runs under the default GCP compute service account, the following
command grants this service account permissions to write into the bucket.

```shell
GOOGLE_CLOUD_PROJECT=... # The project running the builds
BUCKET_NAME="cloud-cpp-community-publiclogs"
PROJECT_NUMBER=$(gcloud projects list \
    --filter="project_id=${GOOGLE_CLOUD_PROJECT}" \
    --format="value(project_number)" \
    --limit=1)

gsutil iam ch \
    "serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com:objectAdmin" \
    "gs://${BUCKET_NAME}"
```

## Create the Docker image

We use buildpack to compile the code in the `function/` directory into a Docker
image. At the end of this build the docker image will reside in your
workstation. We will then push the image to GCR (Google Container Registry) and
use it from Cloud Run.

```shell
pack build  --builder gcr.io/buildpacks/builder:latest \
     --env "GOOGLE_FUNCTION_SIGNATURE_TYPE=cloudevent" \
     --env "GOOGLE_FUNCTION_TARGET=IndexBuildLogs" \
     --path "ci/cloudbuild/notifiers/logs/function" \
     "gcr.io/${GOOGLE_CLOUD_PROJECT}/index-build-logs"
```

## Push the Docker image to GCR

```shell
docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/index-build-logs:latest"
```

## Deploy to Cloud Run

```shell
gcloud run deploy index-build-logs \
    --project="${GOOGLE_CLOUD_PROJECT}" \
    --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/index-build-logs:latest" \
    --set-env-vars="BUCKET_NAME=${BUCKET_NAME}" \
    --region="us-central1" \
    --platform="managed" \
    --no-allow-unauthenticated
```

## Set up a trigger

Note: This command only needs to be run once. It is here in case we ever move
the build to a different project.

Deployments in Cloud Run are (basically) http servers, a trigger converts the
Cloud Pub/Sub messages generated by Cloud Build into events that can be consumed
by the deployment. Note that this is the step where we specify the
`cloud-builds` topic as a source of these events.

```shell
gcloud beta eventarc triggers create index-build-logs-trigger \
    --project="${GOOGLE_CLOUD_PROJECT}" \
    --location="us-central1" \
    --destination-run-service="index-build-logs" \
    --destination-run-region="us-central1" \
    --transport-topic="cloud-builds" \
    --matching-criteria="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --service-account="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
```

## Testing

To test a new version change a few parameters in the previous steps, first,
create a different Docker image:

```shell
pack build  --builder gcr.io/buildpacks/builder:latest \
     --env "GOOGLE_FUNCTION_SIGNATURE_TYPE=cloudevent" \
     --env "GOOGLE_FUNCTION_TARGET=IndexBuildLogs" \
     --path "ci/cloudbuild/notifiers/logs/function" \
     "gcr.io/${GOOGLE_CLOUD_PROJECT}/index-build-logs-test"
```

Push this image to GCR:

```shell
docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/index-build-logs-test:latest"
```

Run a different deployment, change an environment variable to write to
`index-test.html` instead of `index.html`:

```shell
gcloud run deploy index-build-logs-test \
    --project="${GOOGLE_CLOUD_PROJECT}" \
    --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/index-build-logs-test:latest" \
    --set-env-vars="BUCKET_NAME=${BUCKET_NAME}" \
    --set-env-vars="DESTINATION=index-test.html" \
    --set-env-vars="ENABLE_DEBUG=yes" \
    --region="us-central1" \
    --platform="managed" \
    --no-allow-unauthenticated
```

And create a separate trigger:

```shell
gcloud beta eventarc triggers create index-build-logs-test-trigger \
    --project="${GOOGLE_CLOUD_PROJECT}" \
    --location="us-central1" \
    --destination-run-service="index-build-logs-test" \
    --destination-run-region="us-central1" \
    --transport-topic="cloud-builds" \
    --matching-criteria="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --service-account="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
```

After you are finished testing you can cleanup:

```shell
gcloud beta eventarc triggers delete index-build-logs-test-trigger \
    --project="${GOOGLE_CLOUD_PROJECT}" \
    --location="us-central1"
gcloud run services delete index-build-logs-test \
    --project="${GOOGLE_CLOUD_PROJECT}" \
    --region="us-central1" \
    --platform="managed"
```

[docker]: https://docker.com/
[pack-install]: https://buildpacks.io/docs/install-pack/
