Skip to content

Commit

Permalink
Ability to template path of published badge
Browse files Browse the repository at this point in the history
  • Loading branch information
leg100 committed Oct 4, 2019
1 parent 04d4068 commit 09ab0bf
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 13 deletions.
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

A Cloud Function that generates Cloud Build badges.

## Summary

The function subscribes to events published by Cloud Build. The events contain information on the status of the progress and completion of a build. The function copies a badge reflecting that status to a known URL, which can be hard-coded in a repository `README` (as seen above).

## Installation

### Upload Badges
Expand Down Expand Up @@ -43,9 +47,19 @@ Grant permissions to read and write to the bucket:
gsutil iam ch serviceAccount:cloud-build-badge@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com:legacyBucketReader,legacyObjectReader,legacyBucketWriter gs://${GOOGLE_CLOUD_PROJECT}-badges/
```

# Customise Path

You can customise the path in the bucket at which the badge gets published, using a template string. The default is:

`builds/${repo}/branches/${branch}.svg`

Where `${repo}` and `${branch}` refer to the name of the repository and branch that triggered the build. Only these two variables are available.

Set the environment variable `TEMPLATE_PATH` accordingly when deploying the function in the next step.

## Deploy

Deploy the function:
Deploy the function. Note you can customise the path at which the badge gets produced, using a template string,

```bash
gcloud functions deploy cloud-build-badge \
Expand All @@ -54,9 +68,21 @@ gcloud functions deploy cloud-build-badge \
--entry-point build_badge \
--service-account cloud-build-badge@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \
--trigger-topic=cloud-builds \
--set-env-vars BADGES_BUCKET=${GOOGLE_CLOUD_PROJECT}-badges
--set-env-vars BADGES_BUCKET=${GOOGLE_CLOUD_PROJECT}-badges,TEMPLATE_PATH='builds/${repo}/branches/${branch}.svg'
```

## Use

Embed the badge in your README, replacing `${repo}` and `${branch}` with the name of your repository and the branch you want to show the latest status for:

```
![Cloud Build](https://storage.googleapis.com/${GOOGLE_CLOUD_PROJECT}-badges/builds/${repo}/branches/${branch})
```

If you've customised the path using `TEMPLATE_PATH`, ensure it is reflected in the URL above.

Now trigger a Cloud Build build (e.g. by pushing a commit, or directly via the Google Cloud console). You should see the badge update to reflect the build status.

## Test

There is a `make` task for running integration tests against the deployed function:
Expand Down
12 changes: 9 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json
import os
import re
from string import Template


def copy_badge(bucket_name, obj, new_obj):
Expand Down Expand Up @@ -32,20 +33,25 @@ def build_badge(event, context):
decoded = base64.b64decode(event['data']).decode('utf-8')
data = json.loads(decoded)

bucket = os.environ['BADGES_BUCKET']

try:
repo = data['source']['repoSource']['repoName']
branch = data['source']['repoSource']['branchName']

if repo.startswith('github_') or repo.startswith('bitbucket_'):
# mirrored repo format: (github|bitbucket)_<owner>_<repo>
repo = repo.split('_', 2)[-1]
except KeyError:
# github app
repo = data['substitutions']['REPO_NAME']
branch = data['substitutions']['BRANCH_NAME']
finally:
src = 'badges/{}.svg'.format(data['status'].lower())
dest = 'builds/{}.svg'.format(repo)
tmpl = os.environ.get('TEMPLATE_PATH',
'builds/${repo}/branches/${branch}.svg')

bucket = os.environ['BADGES_BUCKET']
src = 'badges/{}.svg'.format(data['status'].lower())
dest = Template(tmpl).substitute(repo=repo, branch=branch)

copy_badge(bucket, src, dest)

Expand Down
33 changes: 25 additions & 8 deletions tests/test_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,43 +50,60 @@ def github_app():
return {
"status": "SUCCESS",
"substitutions": {
"REPO_NAME": "webapp"
"REPO_NAME": "webapp",
"BRANCH_NAME": "feature/fish"
}
}


@pytest.fixture
def env_vars(monkeypatch):
def badges_bucket(monkeypatch):
monkeypatch.setenv('BADGES_BUCKET', 'my-badges-bucket')


@pytest.fixture
def custom_template_path(monkeypatch):
monkeypatch.setenv('TEMPLATE_PATH', 'builds/${repo}-${branch}.svg')


@pytest.fixture
def patches(mocker):
mocker.patch('main.copy_badge')


def test_mirrored_repo(mirrored_repo, env_vars, patches):
def test_mirrored_repo(mirrored_repo, badges_bucket, patches):
main.build_badge(mirrored_repo, None)

main.copy_badge.assert_called_once_with(
'my-badges-bucket',
'badges/success.svg',
'builds/webapp.svg')
'builds/webapp/branches/feature/fish.svg')


def test_github_app(github_app, env_vars, patches):
def test_github_app(github_app, badges_bucket, patches):
main.build_badge(github_app, None)

main.copy_badge.assert_called_once_with(
'my-badges-bucket',
'badges/success.svg',
'builds/webapp.svg')
'builds/webapp/branches/feature/fish.svg')


def test_cloud_source_repo(cloud_source_repo, badges_bucket, patches):
main.build_badge(cloud_source_repo, None)

main.copy_badge.assert_called_once_with(
'my-badges-bucket',
'badges/working.svg',
'builds/webapp/branches/master.svg')


def test_custom_template_path(cloud_source_repo, badges_bucket,
custom_template_path, patches):

def test_cloud_source_repo(cloud_source_repo, env_vars, patches):
main.build_badge(cloud_source_repo, None)

main.copy_badge.assert_called_once_with(
'my-badges-bucket',
'badges/working.svg',
'builds/webapp.svg')
'builds/webapp-master.svg')

0 comments on commit 09ab0bf

Please sign in to comment.