Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .assay.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"suites": [
"suite/api.go"
],
"include": [
"."
]
}
15 changes: 14 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,17 @@ jobs:
run: |
npm -C src/github.com/${{ github.repository }}/cloud \
run -- cdk deploy ${{ matrix.stack }}-latest \
-c vsn=latest
-c vsn=latest \
--outputs-file $GITHUB_WORKSPACE/stack.json

##
## discover url of newly deployed api before the testing
- name: discover
id: discover
run: |
echo ::set-output name=target::$(jq -r '.["${{ matrix.stack }}-pr${{ github.event.number }}"] | to_entries | .[] | select(.key|test("GatewayEndpoint.*")) | .value ' < $GITHUB_WORKSPACE/stack.json)

- uses: assay-it/github-actions-webhook@latest
with:
secret: ${{ secrets.ASSAY_SECRET_KEY }}
target: ${{ steps.discover.outputs.target }}
21 changes: 19 additions & 2 deletions .github/workflows/carry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:

jobs:
it:
strategy:
matrix:
stack: [scud]
runs-on: ubuntu-latest
steps:

Expand Down Expand Up @@ -46,5 +49,19 @@ jobs:
- name: cdk deploy
run: |
npm -C src/github.com/${{ github.repository }}/cloud \
run -- cdk deploy scud-${{ github.event.release.name }} \
-c vsn=${{ github.event.release.name }}
run -- cdk deploy ${{ matrix.stack }}-${{ github.event.release.name }} \
-c vsn=${{ github.event.release.name }} \
--outputs-file $GITHUB_WORKSPACE/stack.json

##
## discover url of newly deployed api before the testing
- name: discover
id: discover
run: |
echo ::set-output name=target::$(jq -r '.["${{ matrix.stack }}-pr${{ github.event.number }}"] | to_entries | .[] | select(.key|test("GatewayEndpoint.*")) | .value ' < $GITHUB_WORKSPACE/stack.json)

- uses: assay-it/github-actions-webhook@latest
with:
secret: ${{ secrets.ASSAY_SECRET_KEY }}
target: ${{ steps.discover.outputs.target }}

4 changes: 2 additions & 2 deletions .github/workflows/clean.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
##
## Clean Sandbox of Pull Request
##
name: spawn
name: clean
on:
pull_request:
types:
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
- name: cdk destroy
run: |
npm -C src/github.com/${{ github.repository }}/cloud \
run -- cdk destroy ${{ matrix.stack }}-pr${{ github.event.number }} \
run -- cdk destroy -f ${{ matrix.stack }}-pr${{ github.event.number }} \
-c vsn=pr${{ github.event.number }}

- uses: thollander/actions-comment-pull-request@master
Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/spawn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,20 @@ jobs:
run: |
npm -C src/github.com/${{ github.repository }}/cloud \
run -- cdk deploy ${{ matrix.stack }}-pr${{ github.event.number }} \
-c vsn=pr${{ github.event.number }}
-c vsn=pr${{ github.event.number }} \
--outputs-file $GITHUB_WORKSPACE/stack.json

##
## discover url of newly deployed api before the testing
- name: discover
id: discover
run: |
echo ::set-output name=target::$(jq -r '.["${{ matrix.stack }}-pr${{ github.event.number }}"] | to_entries | .[] | select(.key|test("GatewayEndpoint.*")) | .value ' < $GITHUB_WORKSPACE/stack.json)

- uses: assay-it/github-actions-webhook@latest
with:
secret: ${{ secrets.ASSAY_SECRET_KEY }}
target: ${{ steps.discover.outputs.target }}

- uses: buildsville/add-remove-label@v1
with:
Expand Down
134 changes: 112 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,75 @@
# scud-golang
<p align="center">
<img src="./doc/logo.gif" height="240" />
<h3 align="center">Blueprint: Serverless Golang</h3>
<p align="center"><strong>Skeleton of Golang serverless application built with AWS CDK</strong></p>

<p align="center">
<!-- Documentation -->
<a href="https://pkg.go.dev/github.com/fogfish/blueprint-serverless-golang">
<img src="https://pkg.go.dev/badge/github.com/fogfish/blueprint-serverless-golang" />
</a>
<!-- Build Status -->
<a href="https://github.com/fogfish/blueprint-serverless-golang/actions/">
<img src="https://github.com/fogfish/blueprint-serverless-golang/workflows/build/badge.svg" />
</a>
<!-- GitHub -->
<a href="http://github.com/fogfish/blueprint-serverless-golang">
<img src="https://img.shields.io/github/last-commit/fogfish/blueprint-serverless-golang.svg" />
</a>
<!-- Coverage -->
<a href="https://coveralls.io/github/fogfish/blueprint-serverless-golang?branch=master">
<img src="https://coveralls.io/repos/github/fogfish/blueprint-serverless-golang/badge.svg?branch=master" />
</a>
<!-- Go Card -->
<a href="https://goreportcard.com/report/github.com/fogfish/blueprint-serverless-golang">
<img src="https://goreportcard.com/badge/github.com/fogfish/blueprint-serverless-golang" />
</a>
<!-- Maintainability -->
<a href="https://codeclimate.com/github/fogfish/blueprint-serverless-golang/maintainability">
<img src="https://api.codeclimate.com/v1/badges/1b00f59c9634d9d479cf/maintainability" />
</a>
</p>
</p>

---

This project crafts a fully functional template of Golang serverless RESTful application for Amazon Web Services. The template is a hybrid solution, composed of pure "application logic" developed with Golang, TypeScript-based Infrastructure as a Code implemented on top of AWS CDK and couple of open source libraries to flavour development experience.


## Inspiration

[AWS CDK](https://aws.amazon.com/cdk) is amazing technology to automate the development and operation of application into one process and one codebase.

However, seeding of new repository for development of Golang serverless application requires a boilerplate code. This template helps you to focus on the application development than waste a time with establish project layout, configure AWS CDK, setting up CI/CD and figuring out how to testing the application. All this is resolved within this template.

## Installation

This template is fully functional "Hello World" like application that delivers a skeleton for Golang serverless development with AWS CDK. Clone the repository and follow [Getting started](#getting-started) instructions to evaluate its applicability for your purposes. It should take less than 5 minutes to build and deploy the template.

This project is a template of Golang serverless RESTful application for Amazon Web Services. This is a hybrid of pure Golang code (application logic), TypeScript AWS CDK (Infrastructure as a Code) and few libraries to flavour development experience.
```
go get github.com/fogfish/blueprint-serverless-golang
```

<!--

TODO:
* How To use GitHub template feature
* How To upgrade the template in existing app
* How To Customize Template

-->

## Getting started

**Let's have a look on the repository structure**

The structure resembles the standard package layout proposed by [in this blog post](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1) with a few simple rules:
The structure resembles the standard package layout proposed in [this blog post](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1):

1. the root package contains core types to describe domain of your application. A simple types that has no dependency to technology.

2. Use sub-packages to isolate dependencies to external technologies so that this is a bridge between your domain and technology adaptation.
2. Use sub-packages to isolate dependencies to external technologies so that they act as bridge between your domain and technology adaptation.

3. Main package builds a lambda code and ties everything together. The application might produce multiple binaries (aka multiple lambda functions)
3. Main packages build lambda functions and ties everything together.

```
github.com/.../the-beautiful-app
Expand All @@ -34,39 +90,50 @@ github.com/.../the-beautiful-app
├─ cloud // IaC, aws cdk application
| └─ ... // It orchestrate everything
|
└─ .github
└─ ... // CI/CD with GitHub Actions

├─ .github
| └─ ... // CI/CD with GitHub Actions
|
└─ suite // api testing suite
├─ api.go
└─ ...
```

### Dependencies
### Development workflows

**dependencies**

The application requires 3rd party libraries for dev and opts. Fetch them with the following commands:

```bash
# Golang deps
go get -d ./...

# AWS CDK TypeScript deps
npm -C cloud install
```

### Test
**unit testing**

Test the Golang application only and its IaC
Test the Golang application and its cloud infrastructure

```bash
# Golang unit testing
go test ./...

# AWS CDK TypeScript testing
npm -C cloud run test
npm -C cloud run lint
```

### Build
**build**

Build entire application (both Golang and its AWS Infrastructure). It should compile Golang code, assemble binaries for AWS Lambda and produce AWS CloudFormation template

```bash
npm -C cloud run -- cdk synth
npm -C cloud run -- cdk synth
```

### Deploy
**deploy**

Deploy an application to AWS account, it requires a valid AWS credentials either access keys or assumed roles.

Expand All @@ -80,22 +147,45 @@ In few seconds, the application becomes available at
curl https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/api/scud
```

### Destroy
**destroy**

Destroy the application and remove all its AWS resource
Destroy the application and remove all its resource from AWS account

```bash
cd cloud
npm -C cloud run -- cdk destroy
```

### CI/CD

The project uses GitHub Actions for CI/CD. The following workflows are supported:
## Continuos Delivery

* **checks** (`golang.yml`, `cloud.yml`) the quality of software assets with scope on unit tests only every time a new change is proposed via Pull Request. CI/CD does checks in parallel for Golang and TypeScript IaC;
Continuos Integration and Delivery is implemented using GitHub Actions. It consists of multiple [.github/workflows](.github/workflows):

* **checks** (`golang.yml`, `cloud.yml`) the quality of software assets with scope on unit tests only. Checks are executed in parallel for application logic and infrastructure every time a new change is proposed via Pull Request.
* **spawns** (`spawn.yml`) a sandbox(ed) deployment of the application to target AWS account for continuous integrations;
* **builds** (`build.yml`) validates quality of `main` branch once Pull Request is merge. The pipeline is also updates the development environment in the target AWS account;
* **carries** (`carry.yml`) application snapshot to production environment;
* **builds** (`build.yml`) validates quality of `main` branch once Pull Request is merge. Upon the quality check completion, the pipeline deploys changes to the development environment at target AWS account;
* **carries** (`carry.yml`) "immutable" application snapshot to production environment when GitHub release is published;
* **cleans** (`clean.yml`) sandbox environment after Pull Request is either merged or closed.


## How To Contribute

The library is [MIT](LICENSE) licensed and accepts contributions via GitHub pull requests:

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request


### commit message

The commit message helps us to write a good release note, speed-up review process. The message should address two question what changed and why. The project follows the template defined by chapter [Contributing to a Project](http://git-scm.com/book/ch5-2.html) of Git book.

### bugs

If you experience any issues with the library, please let us know via [GitHub issues](https://github.com/fogfish/blueprint-serverless-golang/issue). We appreciate detailed and accurate reports that help us to identity and replicate the issue.

## License

[![See LICENSE](https://img.shields.io/github/license/fogfish/blueprint-serverless-golang.svg?style=for-the-badge)](LICENSE)
2 changes: 1 addition & 1 deletion aws/lambda/scud/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package main

import (
"github.com/aws/aws-lambda-go/lambda"
"github.com/fogfish/blueprint-serverless-golang/http"
µ "github.com/fogfish/gouldian"
"github.com/fogfish/scud-golang/http"
)

func main() {
Expand Down
Binary file added doc/logo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion http/api.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package http

import (
scud "github.com/fogfish/blueprint-serverless-golang"
µ "github.com/fogfish/gouldian"
"github.com/fogfish/gouldian/path"
"github.com/fogfish/scud-golang"
)

// ServiceScud is and example RESTfull Service
Expand Down
2 changes: 1 addition & 1 deletion http/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package http_test
import (
"testing"

"github.com/fogfish/blueprint-serverless-golang/http"
µ "github.com/fogfish/gouldian"
"github.com/fogfish/gouldian/mock"
"github.com/fogfish/it"
"github.com/fogfish/scud-golang/http"
)

func TestLookup(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion stub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package scud_test
import (
"testing"

scud "github.com/fogfish/blueprint-serverless-golang"
"github.com/fogfish/it"
"github.com/fogfish/scud-golang"
)

func TestStub(t *testing.T) {
Expand Down
36 changes: 36 additions & 0 deletions suite/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package suite

/*

See following projects for details about testing strategy
https://github.com/assay-it/blueprint-continuous-quality
https://github.com/assay-it/blueprint-serverless-api

*/

import (
"github.com/assay-it/sdk-go/assay"
ç "github.com/assay-it/sdk-go/cats"
"github.com/assay-it/sdk-go/http"
ƒ "github.com/assay-it/sdk-go/http/recv"
ø "github.com/assay-it/sdk-go/http/send"
scud "github.com/fogfish/blueprint-serverless-golang"
)

var host = assay.Host("")

// TestLookup endpoint
func TestLookup() assay.Arrow {
var seq []scud.Stub

return http.Join(
ø.GET("%s/scud", host),
ƒ.Code(http.StatusCodeOK),
ƒ.ServedJSON(),
ƒ.Recv(&seq),
).Then(
ç.Value(&seq).Is(&[]scud.Stub{
{ID: "a"}, {ID: "b"}, {ID: "c"},
}),
)
}