diff --git a/.github/workflows/create-diagram.yml b/.github/workflows/create-diagram.yml
index f45245e5..8d4fffc2 100644
--- a/.github/workflows/create-diagram.yml
+++ b/.github/workflows/create-diagram.yml
@@ -4,7 +4,7 @@ on:
tags:
- v*
branches:
- - master
+ - main
pull_request:
jobs:
repo-visuals:
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 00000000..d8703934
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,75 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+name: Deploy to k8s
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+env:
+ PROJECT_ID: ${{ secrets.GKE_PROJECT }} # contini-XXX-de5a
+ GKE_CLUSTER: gke-test-2022 # Add your cluster name here.
+ GKE_ZONE: us-central1 # Add your cluster zone here.
+ DEPLOYMENT_NAME: gke-hello-app # Add your deployment name here.
+ IMAGE: go-hello-world
+
+jobs:
+ setup-build-publish-deploy:
+ name: Setup, Build, Publish, and Deploy
+ runs-on: ubuntu-latest
+ environment: production
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ # Setup gcloud CLI
+ - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7
+ with:
+ service_account_key: ${{ secrets.GKE_SA_KEY }}
+ project_id: ${{ secrets.GKE_PROJECT }}
+
+ # Configure Docker to use the gcloud command-line tool as a credential
+ # helper for authentication
+ - run: |-
+ gcloud --quiet auth configure-docker
+
+ # Get the GKE credentials so we can deploy to the cluster
+ - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e
+ with:
+ cluster_name: ${{ env.GKE_CLUSTER }}
+ location: ${{ env.GKE_ZONE }}
+ credentials: ${{ secrets.GKE_SA_KEY }}
+
+ # Build the Docker image
+ - name: Build
+ run: |-
+ docker build \
+ --tag "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA" \
+ --build-arg GITHUB_SHA="$GITHUB_SHA" \
+ --build-arg GITHUB_REF="$GITHUB_REF" \
+ .
+
+ # Push the Docker image to Google Container Registry
+ - name: Publish
+ run: |-
+ docker push "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA"
+
+ # Set up kustomize
+ - name: Set up Kustomize
+ run: |-
+ curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v3.1.0/kustomize_3.1.0_linux_amd64
+ chmod u+x ./kustomize
+
+ # Deploy the Docker image to the GKE cluster
+ - name: Deploy
+ run: |-
+ ./kustomize edit set image gcr.io/$PROJECT_ID/$IMAGE:latest=gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA
+ ./kustomize build . | kubectl apply -f -
+ kubectl rollout status deployment/$DEPLOYMENT_NAME
+ kubectl get services -o wide
diff --git a/.github/workflows/google.yml b/.github/workflows/google.yml
deleted file mode 100644
index 28e42554..00000000
--- a/.github/workflows/google.yml
+++ /dev/null
@@ -1,96 +0,0 @@
-# This workflow will build a docker container, publish it to Google Container Registry, and deploy it to GKE when a release is created
-#
-# To configure this workflow:
-#
-# 1. Ensure that your repository contains the necessary configuration for your Google Kubernetes Engine cluster, including deployment.yml, kustomization.yml, service.yml, etc.
-#
-# 2. Set up secrets in your workspace: GKE_PROJECT with the name of the project and GKE_SA_KEY with the Base64 encoded JSON service account key (https://github.com/GoogleCloudPlatform/github-actions/tree/docs/service-account-key/setup-gcloud#inputs).
-#
-# 3. Change the values for the GKE_ZONE, GKE_CLUSTER, IMAGE, and DEPLOYMENT_NAME environment variables (below).
-#
-# For more support on how to run the workflow, please visit https://github.com/GoogleCloudPlatform/github-actions/tree/master/example-workflows/gke
-
-name: Build and Deploy to GKE
-
-#on:
-# release:
-# types: [created]
-on:
- push:
- branches:
- - master
-
-
-env:
- PROJECT_ID: ${{ secrets.GKE_PROJECT }}
- GKE_CLUSTER: gsd-stable # using v1.15 (future versions won't allow deployment.yml) https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/
- GKE_ZONE: us-central1-c
- DEPLOYMENT_NAME: gke-from-github
- IMAGE: hello-world
-
-jobs:
- setup-build-publish-deploy:
- name: Setup, Build, Publish, and Deploy
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout
- uses: actions/checkout@v2
-
- # Setup gcloud CLI
- - uses: GoogleCloudPlatform/github-actions/setup-gcloud@0.1.3
- with:
- service_account_key: ${{ secrets.GKE_SA_KEY }}
- project_id: ${{ secrets.GKE_PROJECT }}
-
- # Configure Docker to use the gcloud command-line tool as a credential
- # helper for authentication
- - run: |-
- gcloud --quiet auth configure-docker
-
- # Get the GKE credentials so we can deploy to the cluster
- - run: |-
- gcloud container clusters get-credentials "$GKE_CLUSTER" --zone "$GKE_ZONE"
-
- # Build the Docker image
- - name: Build
- run: |-
- docker build \
- --tag "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA" \
- --build-arg GITHUB_SHA="$GITHUB_SHA" \
- --build-arg GITHUB_REF="$GITHUB_REF" \
- .
-
- # Push the Docker image to Google Container Registry
- - name: Publish
- run: |-
- docker push "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA"
-
-
- - name: Build latest
- run: |-
- docker build \
- --tag "gcr.io/$PROJECT_ID/$IMAGE:latest" \
- --build-arg GITHUB_SHA="$GITHUB_SHA" \
- --build-arg GITHUB_REF="$GITHUB_REF" \
- .
-
- - name: Publish latest
- run: |-
- docker push "gcr.io/$PROJECT_ID/$IMAGE:latest"
-
-
-
- # Set up kustomize
- - name: Set up Kustomize
- run: |-
- curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v3.1.0/kustomize_3.1.0_linux_amd64
- chmod u+x ./kustomize
-
- # Deploy the Docker image to the GKE cluster
- - name: Deploy
- run: |-
- ./kustomize edit set image gcr.io/PROJECT_ID/IMAGE:TAG=gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA
- ./kustomize build . | kubectl apply -f -
- kubectl rollout status deployment/$DEPLOYMENT_NAME
- kubectl get services -o wide
diff --git a/.github/workflows/main-test.yml.backup b/.github/workflows/main-test.yml.backup
new file mode 100644
index 00000000..4eb753df
--- /dev/null
+++ b/.github/workflows/main-test.yml.backup
@@ -0,0 +1,39 @@
+# Used to test things during PR's that would normally only happen on main branch
+#
+# eg updates to dynamodb table
+#
+
+name: Main CI (TESTING for PRs)
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+
+env:
+ IMAGE_NAME: go-hello-world
+ GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }}
+
+jobs:
+
+ buildtest:
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: checkout repo
+ uses: actions/checkout@v2
+
+ - name: Create DynamboDB Table in AWS - To store metadata (one-time)
+ run: make create_table
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ AWS_DEFAULT_REGION: us-east-2
+
+ # - name: Create tags in DynamboDB Table in AWS - Metadata for this commit
+ # run: make create_tags
+ # env:
+ # PIPELINE_ID: ${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}
+ # AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ # AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ # AWS_DEFAULT_REGION: us-east-2
\ No newline at end of file
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ef9c53b8..cef16f81 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,10 +1,10 @@
-name: CI
+name: Main CI
on:
push:
# Publish `master` as Docker `latest` image.
branches:
- - master
+ - main
# Publish `v1.2.3` tags as releases.
tags:
@@ -12,120 +12,66 @@ on:
# Run tests for any PRs.
pull_request:
-
-env:
- IMAGE_NAME: go-hello-world
- GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }} # not sure why gh didn't let me create a secret with an underscore in it????????
+ types: [opened, synchronize, reopened]
jobs:
- security:
- runs-on: ubuntu-latest
- if: github.event_name == 'push'
-
- steps:
- - uses: actions/checkout@v2
- - uses: ynniss/golang-security-action@master
- with:
- CODE_PATH: "./src/"
-
- security-gosec:
- runs-on: ubuntu-latest
- env:
- GO111MODULE: on
- steps:
- - name: Checkout Source
- uses: actions/checkout@v2
- - name: Run Gosec Security Scanner
- uses: securego/gosec@master
- with:
- args: ./...
build:
runs-on: ubuntu-latest
- if: github.event_name == 'push'
+# if: github.event_name == 'push'
steps:
- - uses: actions/checkout@v2
-
- # this will cause a failure which is only in some demos but annoying in others
- #- uses: ynniss/golang-security-action@master
- # with:
- # #CODE_PATH: "./src/" # <<< we should move our go source into a generic src container so the refernce app is nicely organized and it's easier to build/find source
- # CODE_PATH: "./"
-
-
-
-
-
-
-
-
-
-
-
-
+ - name: checkout code
+ uses: actions/checkout@v2
- name: Tests
run: make test
-
+
- name: Build the Go package
run: make build
+ - name: Security Tests
+ run: make security
+
+ - name: Archive security results
+ uses: actions/upload-artifact@v2
+ with:
+ name: security-report
+ path: security-report
+
+
- name: Run the Go package locally (detached)
run: make run
- #- name: Create DynamboDB Table in AWS
- # run: make create_table
- # env:
- # FOO: ${{ secrets.FOO }}
- # BAR: "BAZ"
- # AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- # AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- # AWS_DEFAULT_REGION: us-east-2
+# This is only used to initially create the table - need a cleaner way to include this,
+# and have it do nothing if the table exists. Make currently ignores error
+ - name: Create DynamboDB Table in AWS - To store metadata (one-time)
+ run: make create_table
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ AWS_DEFAULT_REGION: us-east-2
- - name: Create tags in DynamboDB Table in AWS
+ - name: Create tags in DynamboDB Table in AWS - Metadata for this commit
run: make create_tags
env:
- FOO: ${{ secrets.FOO }}
- BAR: "BAZ"
+ PIPELINE_ID: ${GITHUB_RUN_ID}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: us-east-2
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Push image
+ run: make push
-
-
-
-
-
-
- # this was just in here to prove our the publish, should actually edit the make build do write the correct image name then we can remove this step
- - name: Build image
- run: docker build . --file Dockerfile --tag $IMAGE_NAME
-
- # this is a bit verbose so probably time we wrapped it in make (it was just a copy/paste from github actions anyway)
- - name: Log into registry and Push image
- run: |
- echo "${{ secrets.GH_PACKAGES }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin
-
- IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME
-
- # Change all uppercase to lowercase
- IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
-
- # Strip git ref prefix from version
- VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
-
- # Strip "v" prefix from tag name
- [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
-
- # Use Docker `latest` tag convention
- [ "$VERSION" == "master" ] && VERSION=latest
-
- echo IMAGE_ID=$IMAGE_ID
- echo VERSION=$VERSION
-
- docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
- docker push $IMAGE_ID:$VERSION
+ call-verify:
+ uses: ./.github/workflows/verify.yml
+ needs: [build]
+ secrets: inherit
diff --git a/.github/workflows/playground.yml b/.github/workflows/playground.yml
new file mode 100644
index 00000000..f36e864f
--- /dev/null
+++ b/.github/workflows/playground.yml
@@ -0,0 +1,38 @@
+# These are pipeline steps we're testing that aren't GSD-like yet
+name: Playground
+
+on:
+ push:
+ # Publish `master` as Docker `latest` image.
+ branches:
+ - main
+
+ # Publish `v1.2.3` tags as releases.
+ tags:
+ - v*
+
+ # Run tests for any PRs.
+ pull_request:
+
+jobs:
+
+ golang-security:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ynniss/golang-security-action@master
+ with:
+ CODE_PATH: "./src/"
+
+ gosec-scanner:
+ runs-on: ubuntu-latest
+ env:
+ GO111MODULE: on
+ steps:
+ - name: Checkout Source
+ uses: actions/checkout@v2
+ - name: Run Gosec Security Scanner
+ uses: securego/gosec@master
+ with:
+ args: ./...
diff --git a/.github/workflows/lint.yml b/.github/workflows/quality.yml
similarity index 50%
rename from .github/workflows/lint.yml
rename to .github/workflows/quality.yml
index f7ce46c6..015113b8 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/quality.yml
@@ -1,19 +1,21 @@
-name: lint
on:
push:
- tags:
- - v*
branches:
- - master
+ - main
pull_request:
+ types: [opened, synchronize, reopened]
+
+name: Code Quality
+
jobs:
+
lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: lint
- uses: golangci/golangci-lint-action@v1
+ uses: golangci/golangci-lint-action@v3
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.29
@@ -26,3 +28,21 @@ jobs:
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true
+
+ sonarcloud:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ # Disabling shallow clone is recommended for improving relevancy of reporting
+ fetch-depth: 0
+ - name: SonarCloud Scan
+ uses: sonarsource/sonarcloud-github-action@master
+ with:
+ projectBaseDir: src
+ args: >
+ -Dsonar.organization=fooooooo
+ -Dsonar.projectKey=barrrrrrrrr
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml
deleted file mode 100644
index b6e23b6f..00000000
--- a/.github/workflows/sonar.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-on:
- push:
- branches:
- - master
- pull_request:
- types: [opened, synchronize, reopened]
-name: Code Quality
-
-jobs:
- sonarcloud:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- with:
- # Disabling shallow clone is recommended for improving relevancy of reporting
- fetch-depth: 0
- - name: SonarCloud Scan
- uses: sonarsource/sonarcloud-github-action@master
- with:
- projectBaseDir: src
-# args: >
-# -Dsonar.organization=my-organization
-# -Dsonar.projectKey=my-projectkey
-# -Dsonar.python.coverage.reportPaths=coverage.xml
-# -Dsonar.sources=lib/
-# -Dsonar.test.exclusions=tests/**
-# -Dsonar.tests=tests/
-# -Dsonar.verbose=true
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
diff --git a/.github/workflows/synk.yml b/.github/workflows/synk.yml
new file mode 100644
index 00000000..421b73ff
--- /dev/null
+++ b/.github/workflows/synk.yml
@@ -0,0 +1,19 @@
+name: Snyk - Check for vulnerabilities in this Golang project
+on: push
+jobs:
+ security:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: Run Snyk to check for vulnerabilities
+ uses: snyk/actions/golang@master
+ continue-on-error: true # To make sure that SARIF upload gets called
+ env:
+ SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
+ with:
+ args: --sarif-file-output=snyk.sarif
+ - name: Upload result to GitHub Code Scanning
+ uses: github/codeql-action/upload-sarif@v1
+ with:
+ sarif_file: snyk.sarif
+
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml
new file mode 100644
index 00000000..b9871e2e
--- /dev/null
+++ b/.github/workflows/verify.yml
@@ -0,0 +1,54 @@
+on:
+ workflow_call:
+ secrets:
+ AWS_ACCESS_KEY_ID:
+ required: true
+ AWS_SECRET_ACCESS_KEY:
+ required: true
+ GH_ARTIFACT_TOKEN:
+ required: true
+ DYNAMODB_TABLE:
+ required: true
+
+name: Verify
+env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ TOKEN: ${{ secrets.GH_ARTIFACT_TOKEN }}
+ AWS_DEFAULT_REGION: us-east-2
+
+jobs:
+ verify:
+ runs-on: ubuntu-latest
+ steps:
+ - run: |
+ echo "🎉 The commit ID of the artifact is: $GITCOMMIT"
+ echo "GITCOMMIT=$GITCOMMIT" >> $GITHUB_ENV
+ echo "🎉 The dynamodb table is: $DYNAMODB_TABLE"
+ echo "DYNAMODB_TABLE=$DYNAMODB_TABLE" >> $GITHUB_ENV
+ env:
+ GITCOMMIT: ${{ github.sha }}
+ DYNAMODB_TABLE: ${{ secrets.DYNAMODB_TABLE }}
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Check out gsd-verification-rules repo
+ uses: actions/checkout@v2
+ with:
+ repository: contino/gsd-verification-rules
+ ref: main
+ path: gsd-verification-rules
+ ssh-key: "${{ secrets.SSH_PRIVATE_KEY }}"
+
+ - name: Download all workflow run artifacts
+ uses: actions/download-artifact@v3
+ with:
+ path: gsd-verification-rules
+
+ - name: Run all verification rules
+ run: cd gsd-verification-rules && env && make verify
diff --git a/.gitignore b/.gitignore
index a4a78619..a98b8c76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,4 +17,9 @@ aws.env
# ide specific directories
.idea
-.vscode
\ No newline at end of file
+.vscode
+Makefile
+
+# gsd specific
+gsd-verification-rules
+security-report/*
\ No newline at end of file
diff --git a/Makefile b/Makefile
index c5294026..ffb52450 100644
--- a/Makefile
+++ b/Makefile
@@ -1,64 +1,103 @@
-DOCKER_TAG ?= go-hello-world
-FULL_TAG ?= ${DOCKER_TAG}:${HASH}
-DYNAMODB_TABLE ?= ${DOCKER_TAG}
-PORT ?= "8080"
+3M_IMAGE_NAME ?= flemay/musketeers
+REGISTRY_URL := ghcr.io
+GITHUB_REPOSITORY ?= contino/gsd-hello-world
+IMAGE_NAME ?= go-hello-world
+FULL_TAG ?= ${REGISTRY_URL}/${GITHUB_REPOSITORY}/${IMAGE_NAME}:${HASH}
+DYNAMODB_TABLE ?= ${IMAGE_NAME}-v2
+PORT ?= 8080
+DOCKER_COMPOSE ?= FULL_TAG=${FULL_TAG} docker-compose
GO_TEST_DOCKER_COMPOSE ?= docker-compose run --rm gobase go test -v -cover
AWS_CLI_DOCKER_COMPOSE ?= docker-compose run --rm awscli
-HASH := $(shell git rev-parse HEAD)
-VERACODE_ID?= "someveracodeid"
+HASH := $(shell git rev-parse HEAD)
+ENVFILE ?= aws.template
+PIPELINE_BASE ?= contino/gsd-hello-world
-ENVFILE ?= aws.template
+.DEFAULT_GOAL := help
-envfile:
- echo "from envfile"
- echo "FOO=${FOO}"
- echo "BAR=${BAR}"
+.PHONY: help
+help: ## List of targets with descriptions
+ @echo "\n--------------------- Run [TARGET] [ARGS] or "make help" for more information ---------------------\n"
+ @for MAKEFILENAME in $(MAKEFILE_LIST); do \
+ grep -E '[a-zA-Z_-]+:.*?## .*$$' $$MAKEFILENAME | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'; \
+ done
+ @echo "\n---------------------------------------------------------------------------------------------------\n"
+
+.PHONY: list
+list: pull-3m-image ## Get list of all make targets
+ @echo "list"; \
+ $(DOCKER_RUN_3M) $(MAKE) --no-print-directory _list
+
+.PHONY: _list
+_list:
+ @echo "\n---------------------------------------\nList of available targets:\n---------------------------------------"
+ @$(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
+ @echo "\n---------------------------------------\n"
+
+.PHONY: envfile
+envfile: ## Create envfile
cp $(ENVFILE) aws.env
-.PHONY : build
-build:
+.PHONY: build
+build: ## Build the application
docker build -t ${FULL_TAG} .
+.PHONY: push
+push: dockerlogin ## Push the containerized application
+ docker push ${FULL_TAG}
+
+.PHONY: dockerlogin
+dockerlogin: ## Login to docker registry
+ docker login ${REGISTRY_URL}
+
.PHONY: run
-run:
- docker run -d -p ${PORT}:${PORT} --name ${DOCKER_TAG} ${FULL_TAG}
+run: ## Run the application
+ $(DOCKER_COMPOSE) up -d gohelloworld
+ $(DOCKER_COMPOSE) up healthcheck
.PHONY: down
-down:
- docker rm -f ${DOCKER_TAG}
+down: ## Stop the application
+ $(DOCKER_COMPOSE) down
.PHONY: test
-test: envfile
+test: envfile ## Test the application
${GO_TEST_DOCKER_COMPOSE}
+.PHONY: verify
+verify:
+ git clone git@github.com:contino/gsd-verification-rules.git || true
+ cd gsd-verification-rules && git pull && make verify
+
+.PHONY: security
+security: run ## Run security checks against app
+ rm -rf security-report
+ mkdir -p security-report
+ $(DOCKER_COMPOSE) -p security -f security-compose.yml up
+ $(DOCKER_COMPOSE) -p security -f security-compose.yml down || true
+ @$(MAKE) --no-print-directory down
+
.PHONY: create_table
create_table: envfile
- echo "from create_table"
- echo "FOO=${FOO}"
- echo "BAR=${BAR}"
- ${AWS_CLI_DOCKER_COMPOSE} dynamodb create-table \
- --table-name ${DYNAMODB_TABLE} \
- --attribute-definitions \
- AttributeName=GIT_COMMIT,AttributeType=S \
- AttributeName=VERACODE_ID,AttributeType=S \
- --key-schema \
- AttributeName=GIT_COMMIT,KeyType=HASH \
- AttributeName=VERACODE_ID,KeyType=RANGE \
- --provisioned-throughput \
- ReadCapacityUnits=10,WriteCapacityUnits=5
+ -${AWS_CLI_DOCKER_COMPOSE} dynamodb create-table \
+ --table-name ${DYNAMODB_TABLE} \
+ --attribute-definitions AttributeName=GIT_COMMIT,AttributeType=S \
+ --key-schema AttributeName=GIT_COMMIT,KeyType=HASH \
+ --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 \
+ --tags Key=Permanent,Value=True
+.PHONY: create_tags
create_tags: envfile
${AWS_CLI_DOCKER_COMPOSE} dynamodb put-item \
--table-name ${DYNAMODB_TABLE} \
- --item \
- '{"GIT_COMMIT": {"S": "${HASH}"}, "VERACODE_ID":{"S": ${VERACODE_ID}}}'
+ --item '{ "GIT_COMMIT": {"S": "${HASH}"}, "PIPELINE_BASE":{"S": "${PIPELINE_BASE}"}, "PIPELINE_ID":{"S": "${PIPELINE_ID}"} }'
.PHONY: clean
-clean:
- docker kill ${DOCKER_TAG}
- docker rm ${DOCKER_TAG}
-
+clean: ## Cleanup and remove docker application
+ docker kill ${IMAGE_NAME}
+ docker rm ${IMAGE_NAME}
+.PHONY: pull-3m-image
+pull-3m-image: ## Pull 3M image for local executions
+ docker pull ${3M_IMAGE_NAME}
diff --git a/aws.template b/aws.template
index 2e6b841a..fd7d8bbe 100644
--- a/aws.template
+++ b/aws.template
@@ -2,4 +2,5 @@ FOO
BAR
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
+AWS_SESSION_TOKEN
AWS_DEFAULT_REGION
diff --git a/deployment.yml b/deployment.yml
index 399434d5..2ea2eb57 100644
--- a/deployment.yml
+++ b/deployment.yml
@@ -1,4 +1,4 @@
-# Copyright 2019 Google LLC
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,12 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-apiVersion: apps/v1beta1
+apiVersion: apps/v1
kind: Deployment
metadata:
- name: gke-test
+ name: gke-hello-app
spec:
- replicas: 1
+ replicas: 2
+ selector:
+ matchLabels:
+ app: gke-hello-app
strategy:
rollingUpdate:
maxSurge: 1
@@ -26,15 +29,27 @@ spec:
template:
metadata:
labels:
- app: gke-test
+ app: gke-hello-app
spec:
containers:
- - name: gke-test
- image: gcr.io/contino-919ebf1dd6da5f73/hello-world:latest
+ - name: hello-app
+ image: gcr.io/contini-0fd0de1002f7de5a/go-hello-world:latest
ports:
- containerPort: 8080
- resources:
- requests:
- cpu: 100m
- limits:
- cpu: 100m
+# resources:
+# requests:
+# cpu: 100m
+# limits:
+# cpu: 100m
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: gke-hello-app-service
+spec:
+ type: LoadBalancer
+ ports:
+ - port: 80
+ targetPort: 8080
+ selector:
+ app: gke-hello-app
diff --git a/docker-compose.yml b/docker-compose.yml
index ab618c22..aa103663 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,17 +1,35 @@
version: '3'
+
+networks:
+ default:
+ external: false
+ name: go-hello-world
+
services:
gohelloworld:
- build: .
- image: gohelloworld:latest
+ image: ${FULL_TAG}
ports:
- "8080:8080"
+ healthcheck:
+ test: curl --fail http://localhost:8080 || exit 1
+ interval: 10s
+ retries: 50
+ start_period: 20s
+ timeout: 2s
+ healthcheck:
+ image: alpine/curl
+ command: http://gohelloworld:8080 --max-time 60 --retry-max-time 60 --connect-timeout 5 --retry 10 --retry-connrefused --silent
+
gobase:
image: golang:latest
working_dir: "/app/src"
volumes:
- "./:/app"
+ profiles: ["test"]
awscli:
image: amazon/aws-cli
working_dir: "/app"
env_file:
- - ./aws.env
\ No newline at end of file
+ - ./aws.env
+ profiles: ["aws"]
+
diff --git a/docs/deploy.md b/docs/deploy.md
new file mode 100644
index 00000000..76f312af
--- /dev/null
+++ b/docs/deploy.md
@@ -0,0 +1,38 @@
+# Deployments
+
+A deployment takes a built artifact (ie golang app in a docker container) and deploys it to an environment (a k8s cluster).
+
+## The k8s Environment
+
+We're using GKE from Google Cloud in our example, but any k8s cluster will work.
+
+There are currently a few things we're doing manually to prepare an environment:
+
+- Cluster Creation (Done through Console - Autopilot)
+- IAM Service Account using permissions described here [Deploy to k8s](https://docs.github.com/en/actions/deployment/deploying-to-your-cloud-provider/deploying-to-google-kubernetes-engine) - ie cluster admin, and storage admin (you may have to tweak permissions for your own deployment)
+- `GKE_SA_KEY` in github populated using the json key created from the above service account - ie `cat key.json | base64`
+
+The Cluster `gke-test-2022` lives in tihe project `contini-XXX-de5a` which is `Squad Zero > Andrew Khoury Contino`.
+
+## The deployment
+
+Our github workflow `deploy.yml` ("Deploy to k8s") does the deployment, and is based on [google-github-actions](https://github.com/google-github-actions/setup-gcloud/tree/main/example-workflows/gke).
+
+What it does:
+
+- Sets some key variables `PROJECT_ID`, `GKE_CLUSTER`, `GKE_ZONE`, `DEPLOYMENT_NAME`, `IMAGE`
+- Runs as a production deployment, checks out code, auths to gcloud
+- builds the app, publishes it
+- deploys to k8s after ensuring we're using the newly built image (using a combo of kustomize and kubectl)
+
+What it depends on:
+
+- `kustomization.yml` (to tell it to look for `deployment.yml`)
+- `deployment.yml` (k8s config - app/service name, container, ports, lb etc)
+
+# Todos
+
+- Use dev for this pipeline? And Prod for the prod pipeline?
+- Automate env setup
+- Make this step gsd like, ie `make deploy`
+- Instead of building during this step, leverage the build from the main CI? (build once deploy many)
diff --git a/kustomization.yml b/kustomization.yml
index 989a38cf..a580c34b 100644
--- a/kustomization.yml
+++ b/kustomization.yml
@@ -16,4 +16,3 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yml
-- service.yml
diff --git a/repo-visualizer.svg b/repo-visualizer.svg
index 7a1c7327..bd47336d 100644
--- a/repo-visualizer.svg
+++ b/repo-visualizer.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/run b/run
new file mode 100755
index 00000000..a067f382
--- /dev/null
+++ b/run
@@ -0,0 +1,121 @@
+#!/usr/bin/env bash
+
+# This idea is heavily inspired by: https://github.com/adriancooney/Taskfile
+# FOR WHEN YOU DO NOT WANT TO (OR CANNOT) US MAKE
+# Found this here....
+# https://www.youtube.com/watch?v=SdmYd5hJISM
+
+# Ensure specific failures (add u if you want fail on any missing or unset variable)
+set -eo pipefail
+
+# If we're running in CI we need to disable TTY allocation for docker-compose
+# commands that enable it by default, such as exec and run.
+TTY=""
+if [[ ! -t 1 ]]; then
+ TTY="-T"
+fi
+
+HASH="$(git rev-parse HEAD)"
+
+: "${ENVFILE:=aws.template}"
+: "${IMAGE_NAME_3M:=flemay/musketeers}"
+: "${REGISTRY_URL:=ghcr.io}"
+: "${GITHUB_REPOSITORY:=contino/gsd-hello-world}"
+: "${IMAGE_NAME:=go-hello-world}"
+: "${FULL_TAG:=${REGISTRY_URL}/${GITHUB_REPOSITORY}/${IMAGE_NAME}:${HASH}}"
+: "${DYNAMODB_TABLE:=${IMAGE_NAME}-v2}"
+: "${PORT:=8080}"
+: "${PIPELINE_BASE:=contino/gsd-hello-world}"
+
+# -----------------------------------------------------------------------------
+# Helper functions start with _ and aren't listed in this script's help menu.
+# -----------------------------------------------------------------------------
+
+function _dc {
+ docker-compose run --rm "${@}"
+}
+
+# -----------------------------------------------------------------------------
+
+function envfile { ## Create envfile
+ echo "from envfile"
+ echo "FOO=${FOO}"
+ echo "BAR=${BAR}"
+ cp $ENVFILE aws.env
+}
+
+function build { ## Build the application
+ docker build -t ${FULL_TAG} .
+}
+
+function push { ## Push the containerized application
+ dockerlogin
+ docker push ${FULL_TAG}
+}
+
+function dockerlogin { ## Login to docker registry
+ docker login ${REGISTRY_URL}
+}
+
+function run { ## Run the application
+ docker run -d -p ${PORT}:${PORT} --name ${IMAGE_NAME} ${FULL_TAG}
+}
+
+function down { ## Stop the application
+ docker rm -f ${IMAGE_NAME}
+}
+
+function test { ## Test the application
+ envfile
+ _dc gobase go test -v -cover
+}
+
+function verify {
+ git clone git@github.com:contino/gsd-verification-rules.git || true
+ cd gsd-verification-rules && git pull && make verify
+}
+
+function create_table {
+ envfile
+ echo "from create_table"
+ echo "FOO=${FOO}"
+ echo "BAR=${BAR}"
+ _dc awscli dynamodb create-table \
+ --table-name ${DYNAMODB_TABLE} \
+ --attribute-definitions AttributeName=GIT_COMMIT,AttributeType=S AttributeName=PIPELINE_ID,AttributeType=S \
+ --key-schema AttributeName=GIT_COMMIT,KeyType=HASH AttributeName=PIPELINE_ID,KeyType=RANGE \
+ --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5
+}
+
+function create_tags {
+ envfile
+ _dc awscli dynamodb put-item \
+ --table-name ${DYNAMODB_TABLE} \
+ --item '{ "GIT_COMMIT": {"S": "${HASH}"}, "PIPELINE_BASE":{"S": "${PIPELINE_BASE}"}, "PIPELINE_ID":{"S": "${PIPELINE_ID}"} }'
+}
+
+function clean { ## Cleanup and remove docker application
+ docker kill ${IMAGE_NAME}
+ docker rm ${IMAGE_NAME}
+}
+
+function pull-3m-image { ## Pull 3M image for local executions
+ docker pull ${3M_IMAGE_NAME}
+}
+
+function help {
+ echo -e "\n------------------------------------- Tasks with descriptions -------------------------------------\n"
+ grep -E 'function [a-zA-Z_-]+ {.*?## .*$$' ./run | sort | sed 's|function ||' | awk 'BEGIN {FS = " {.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $1, $2}'
+ echo -e "\n---------------------------------------------------------------------------------------------------\n"
+}
+
+function list {
+ printf "%s [args]\n\nTasks:\n" "${0}"
+
+ compgen -A function | grep -v "^_" | cat -n
+
+ printf "\nExtended help:\n Each task has comments for general usage\n"
+}
+
+TIMEFORMAT=$'\nTask completed in %3lR'
+time "${@:-list}"
\ No newline at end of file
diff --git a/security-compose.yml b/security-compose.yml
new file mode 100644
index 00000000..3db10f3c
--- /dev/null
+++ b/security-compose.yml
@@ -0,0 +1,22 @@
+version: '3'
+
+networks:
+ default:
+ external: false
+ name: go-hello-world
+
+services:
+
+ zap-scan:
+ user: root
+ image: owasp/zap2docker-weekly
+ volumes:
+ - "./security-report:/security-report"
+ command: ["/bin/sh","-c","zap-baseline.py -t http://gohelloworld:8080 > /security-report/zap-security-report.txt || true"]
+
+ # Used for testing but not very good. Waiting to add something better here
+ # nikto-scan:
+ # image: sullo/nikto
+ # volumes:
+ # - "./security-report:/output"
+ # command: -h http://gohelloworld:8080 -o output/nikto-security-report.txt
diff --git a/service.yml b/service.yml
deleted file mode 100644
index 7d6da5b1..00000000
--- a/service.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2019 Google LLC
-#
-# 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.
-
-apiVersion: v1
-kind: Service
-metadata:
- name: gke-test-service
-spec:
- type: LoadBalancer
- ports:
- - port: 80
- targetPort: 8080
- selector:
- app: gke-test
diff --git a/sonar-project.properties b/sonar-project.properties
index a259be2c..6959fee7 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -4,4 +4,4 @@ sonar.projectKey=barrrrrrrrr
# relative paths to source directories. More details and properties are described
# in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/
-sonar.sources=.
+sonar.sources=./src
diff --git a/src/main.go b/src/main.go
index 595de9d8..fd987e3b 100644
--- a/src/main.go
+++ b/src/main.go
@@ -41,7 +41,10 @@ func getOneEvent(w http.ResponseWriter, r *http.Request) {
for _, singleEvent := range events {
if singleEvent.ID == eventID {
- json.NewEncoder(w).Encode(singleEvent)
+ err := json.NewEncoder(w).Encode(singleEvent)
+ if err != nil {
+ log.Printf("Error encoding event: %s Error: %s", singleEvent, err)
+ }
}
}
}
diff --git a/src/main_test.go b/src/main_test.go
index 8e6531dd..171d8871 100644
--- a/src/main_test.go
+++ b/src/main_test.go
@@ -43,12 +43,32 @@ func TestGETHome(t *testing.T) {
if testing.CoverMode() != "" {
c := testing.Coverage()
- if c < 0.8 {
- fmt.Println("Tests passed but coverage failed at", c)
+ if c < 0.1 {
+ fmt.Println("Tests passed but test-coverage below threshold of less than 10%. Current test-coverage is: ", c)
rc = -1
+ os.Exit(rc)
}
+ if c >= 0.1 {
+ fmt.Println("Tests passed and test-coverage is above threshold of at least 10%. Current test-coverage is: ", c)
+ }
}
- os.Exit(rc)
-
}
+
+func TestGetOneEvent(t *testing.T) {
+ t.Run("returns 200 status code", func(t *testing.T) {
+ request, _ := http.NewRequest(http.MethodGet, "/events/1", nil)
+ response := httptest.NewRecorder()
+
+ getOneEvent(response, request)
+
+ got := response.Result().StatusCode
+ want := 200
+
+ if got != want {
+ t.Errorf("got %q, want %q", got, want)
+ }
+ })
+
+
+}
\ No newline at end of file