From b29abf75f82be9e40f59c91c455e8040ed006739 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 12 Aug 2021 13:43:02 -0400 Subject: [PATCH] Auto-deploy smoothie - Use GoReleaser - Add Dockerfile based on Alpine:latest - Publish docker images to our private ghcr.io registry - Run build and test using GH Actions (ci.yml) - Deploy AWS ECS Docker instance to our AWS infrastructure using GH Actions (cd.yml) Note: repository secrets are used to make the auto-deploy work. All the secrets used are in our Gopass repository. `GITHUB_TOKEN` is a reserved GH Actions secret with basic permissions like pushing to organization registries. --- .github/workflows/cd.yml | 156 +++++++++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 33 +++++++++ .gitignore | 4 + .goreleaser.yml | 37 ++++++++++ Dockerfile | 22 ++++++ main.tf | 39 ++++++++++ 6 files changed, 291 insertions(+) create mode 100644 .github/workflows/cd.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .goreleaser.yml create mode 100644 Dockerfile create mode 100644 main.tf diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 000000000..b40ccfd03 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,156 @@ +name: CD + +on: + push: + branches: + - main + pull_request: + + +jobs: + cd: + strategy: + matrix: + go-version: [~1.16] + runs-on: ubuntu-latest + env: + GO111MODULE: "on" + CONTAINER_REPO: "ghcr.io/${{ github.repository }}" + ENVIRONMENT: development + AWS_DEFAULT_REGION: us-east-1 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + steps: + - name: Install Go + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.go-version }} + + - name: Checkout code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + # Remove this later + - name: Clone internal repositories + run: | + git clone -b release https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/charm-internal ../charm + git clone -b master https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/bubbletea-internal ../bubbletea + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + if: github.event_name == 'push' + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build Docker images using GoReleaser + uses: goreleaser/goreleaser-action@master + if: github.event_name == 'push' + with: + version: latest + # https://github.com/goreleaser/goreleaser/discussions/1534 + args: -f .goreleaser.yml --snapshot + + - name: Push Docker images + if: github.event_name == 'push' + run: | + docker push $CONTAINER_REPO:snapshot + docker push $CONTAINER_REPO:$GITHUB_SHA-snapshot + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v1 + with: + # terraform_version: 0.13.0 + cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} + + - name: Terraform Variables + id: tfvars + run: | + TF_VARS=$(cat <Show Plan + + \`\`\`\n + ${process.env.PLAN} + \`\`\` + + + + *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`; + + if (process.env.COMMENT_ID) { + github.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: process.env.COMMENT_ID, + body: output + }) + } else { + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: output + }) + } + + - name: Terraform Plan Status + if: steps.plan.outcome == 'failure' + run: exit 1 + + + - name: Terraform Apply + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + run: terraform apply -auto-approve ${{ steps.tfvars.outputs.vars }} + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..9470cf6f8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + +jobs: + + build: + strategy: + matrix: + go-version: [~1.16] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + # Remove this later + - name: Clone internal repositories + run: | + git clone -b release https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/charm-internal ../charm + git clone -b master https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/bubbletea-internal ../bubbletea + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -v ./... diff --git a/.gitignore b/.gitignore index 53f079059..2ee7702b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ smoothie .ssh .repos +dist +.terraform* +*.tfstate* +*auto.tfvars \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 000000000..89e2409bf --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,37 @@ +project_name: smoothie + +env: + - GO111MODULE=on + - CGO_ENABLED=0 + +before: + hooks: + - go mod download + +builds: + - id: "smoothie" + binary: "smoothie" + ldflags: -s -w -X main.Version={{ .Commit }}-snapshot -X main.CommitSHA={{ .Commit }} + goos: + - linux + goarch: + - amd64 + +dockers: + - image_templates: + - "ghcr.io/charmbracelet/smoothie:snapshot" + - "ghcr.io/charmbracelet/smoothie:{{ .Commit }}-snapshot" + ids: [smoothie] + goarch: amd64 + build_flag_templates: + - --platform=linux/amd64 + - --label=org.opencontainers.image.title={{ .ProjectName }} + - --label=org.opencontainers.image.description={{ .ProjectName }} + - --label=org.opencontainers.image.url=https://github.com/charmbracelet/smoothie + - --label=org.opencontainers.image.source=https://github.com/charmbracelet/smoothie + - --label=org.opencontainers.image.version={{ .Commit }}-snapshot + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.licenses=MIT + dockerfile: Dockerfile + use: buildx diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..de9075197 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM alpine:latest + +RUN apk update && apk add --update nfs-utils git && rm -rf /var/cache/apk/* + +COPY smoothie /usr/local/bin/smoothie + +# Create directories +WORKDIR /smoothie +# Expose data volume +VOLUME /smoothie + +# Environment variables +ENV SMOOTHIE_KEY_PATH "/smoothie/ssh/smoothie_server_ed25519" +ENV SMOOTHIE_REPO_KEYS_PATH "/smoothie/ssh/smoothie_git_authorized_keys" +ENV SMOOTHIE_REPO_PATH "/smoothie/repos" + +# Expose ports +# SSH +EXPOSE 23231/tcp + +# Set the default command +ENTRYPOINT [ "/usr/local/bin/smoothie" ] \ No newline at end of file diff --git a/main.tf b/main.tf new file mode 100644 index 000000000..a6cc616a7 --- /dev/null +++ b/main.tf @@ -0,0 +1,39 @@ +terraform { + backend "s3" { + bucket = "charm-terraform-state" + key = "smoothie-development" + region = "us-east-1" + } +} + +variable "environment" { + default = "development" +} + +variable "aws_region" { + default = "us-east-1" +} + +variable "app_image" { + default = "ghcr.io/charmbracelet/smoothie:snapshot" +} + +variable "force_new_deployment" { + default = false +} + +module "smoothie" { + # source = "../terraform-aws-smoothie" + source = "app.terraform.io/charm/smoothie/aws" + version = "0.1.2" + + environment = var.environment + aws_region = var.aws_region + ecs_task_execution_role_name = "smoothieEcsTaskExecutionRole-${var.environment}" + app_image = var.app_image + app_count = 2 + app_ssh_port = 23231 + fargate_cpu = "1024" + fargate_memory = "2048" + force_new_deployment = var.force_new_deployment +}