Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

Migrated Drone pipelines to GHA #983

Merged
merged 14 commits into from
Feb 17, 2024
1,086 changes: 0 additions & 1,086 deletions .drone.yml

This file was deleted.

218 changes: 214 additions & 4 deletions .github/workflows/tag-build.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,220 @@
---
name: Build release

on:
workflow_dispatch:
workflow_dispatch:
inputs:
artifact-tag:
description: "The tag associated with the artifact to deploy (eg. v1.2.3)."
type: string
required: true
# This is a workaround so that the actor who initiated a workflow run via a workflow dispatch event can determine the run ID of the started workflow run
workflow-tag:
description: "This field adds the provided value to a run step, allowing the calling actor to associate the started run with the GHA run ID."
type: string
required: false
pull_request:
branches:
- master
push:
tags:
- "v*"
branches:
- master

concurrency:
group: "Limit to one build at a time for ref ${{ format('refs/tags/{0}', inputs.artifact-tag) || github.head_ref }}"
camscale marked this conversation as resolved.
Show resolved Hide resolved
cancel-in-progress: true

jobs:
placeholder:
setup:
runs-on: ubuntu-latest
outputs:
gitref: ${{ steps.set-gitref.outputs.gitref }}
environment: ${{ steps.set-variables.outputs.environment }}
version: ${{ steps.set-variables.outputs.version }}
steps:
- run: echo "Placeholder"
# TODO this really needs to move to shared workflows. This is the ~fourth place
# that this logic has been used.
- name: Determine git ref
id: set-gitref
env:
EVENT_NAME: ${{ github.event_name}}
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
REF_TYPE: ${{ github.ref_type }}
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
REF_VALUE: ${{ inputs.artifact-tag || github.head_ref }}
run: |
# If value is a tag
if [ "$EVENT_NAME" == "workflow_dispatch" ] || [ "$REF_TYPE" == "tag" ]; then
echo "gitref=refs/tags/$REF_VALUE" >> "$GITHUB_OUTPUT"
exit 0
fi

# Otherwise, ref must be a branch
echo "gitref=refs/heads/$REF_VALUE" >> "$GITHUB_OUTPUT"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ steps.set-gitref.outputs.gitref }}
- name: Set environment output values
id: set-variables
env:
GITHUB_EVENT_NAME: ${{ github.event_name}}
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
INPUT_VERSION: ${{ inputs.artifact-tag }}
SEMVER_REGEX: ^v?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?:[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
run: |
generate_version() {
# Example: v1.2.3-gen.4+g5678abcd
git describe --tags --match "v[[:digit:]]*.[[:digit:]]*.[[:digit:]]" | sed 's/\(.*\)-\(.*\)-\(.*\)/\1-gen.\2+\3/'
}

get_output_vars() {
case "$GITHUB_EVENT_NAME" in
"workflow_dispatch")
# Case: workflow dispatch event. Pull most vars from inputs.
echo "environment=build-stage"
echo "version=$INPUT_VERSION"
;;
"pull_request")
echo "environment=build-stage"
echo "version=$(generate_version "$GITHUB_EVENT_REF_NAME")"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
;;
"push")
REF_TYPE=$(echo "$GITHUB_EVENT_REF" | cut -d'/' -f2)
# Case: commit push event.
if [ "$REF_TYPE" != "tags" ]; then
echo "environment=build-stage"
echo "version=$(generate_version "$GITHUB_EVENT_REF_NAME")"
return
fi

# Case: tag event with prerelease version.
if [ "${GITHUB_EVENT_REF_NAME#*-}" != "$GITHUB_EVENT_REF_NAME" ]; then
echo "environment=build-stage"
echo "version=$GITHUB_EVENT_REF_NAME"
return
fi

# Case: tag event with release version. Only this
# should go to prod.
echo "environment=build-prod"
echo "version=$GITHUB_EVENT_REF_NAME"
;;
*)
>&2 echo "Unknown GHA event $GITHUB_EVENT_NAME, failing"
exit 1
;;
esac
}

get_output_vars >> "$GITHUB_OUTPUT"

# Validate the semver
. "$GITHUB_OUTPUT" # Load the variables into the current environment
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
(echo "$version" | grep -qP "$SEMVER_REGEX") || (echo "The artifact version $version is not a valid semver-coerced value"; exit 1)

# Log the build details
echo "Built config:" | tee -a "$GITHUB_STEP_SUMMARY"
cat "$GITHUB_OUTPUT" | while read line; do
echo "* $line" | tee -a "$GITHUB_STEP_SUMMARY"
done
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
- name: ${{ inputs.workflow-tag }}
if: inputs.workflow-tag != ''
run: |
# Do nothing
# Each section here could be split out into a separate job, at the cost of slightly increased complexity.
camscale marked this conversation as resolved.
Show resolved Hide resolved
# This would improve the (already somewhat fast) performance a bit, but I'm not sure if it's worth the
# tradeoff.
build-plugins:
needs:
- setup
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-22.04-32core
environment: ${{ needs.setup.outputs.environment }}
permissions:
contents: read
id-token: write
env:
ARTIFACT_DIRECTORY: /tmp/build
steps:
# Setup
- name: Enable performance telemetry/metrics
uses: catchpoint/workflow-telemetry-action@v1
with:
comment_on_pr: false
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ needs.setup.outputs.gitref }}
fetch-depth: 0 # This is required by some of the commands in the makefiles
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: "./go.mod"
cache-dependency-path: "./go.sum"
camscale marked this conversation as resolved.
Show resolved Hide resolved
check-latest: true
- name: Set environment variables for Makefiles
env:
VERSION_TAG: ${{ needs.setup.outputs.version }}
run: |
{
echo "VERSION=${VERSION_TAG##v}"
echo "GITREF=$VERSION_TAG" >> "$GITHUB_ENV"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
echo "GNUMAKEFLAGS=-j$(nproc)"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
} >> "$GITHUB_ENV"
# File artifacts
- name: Build the release tarballs
run: |
# Binaries and Helm charts
make releases helm-package-charts

# Terraform provider and event handler, as appropriate
go install github.com/konoui/lipo@latest # At some point this should be merged into the buildbox
make OS=linux ARCH=amd64 release/terraform release/event-handler
make OS=linux ARCH=arm64 release/terraform
make OS=darwin ARCH=amd64 release/terraform release/event-handler
make OS=darwin ARCH=arm64 release/terraform
make OS=darwin ARCH=universal release/terraform
- name: Collect the build files
run: |
mkdir -pv "$ARTIFACT_DIRECTORY"
cp $(find . '(' -name "*.tar.gz" -o -name "*.tgz" ')' -type f) "$ARTIFACT_DIRECTORY/"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
- name: Generate checksum files for built files
working-directory: ${{ env.ARTIFACT_DIRECTORY }}
run: |
find . '(' -name "*.tar.gz" -o -name "*.tgz" ')' -type f -exec sh -c 'sha256sum "$(basename {})" > "{}.sha256"' \;
camscale marked this conversation as resolved.
Show resolved Hide resolved
echo "Artifacts:"
ls -lh
- name: Assume AWS role for uploading the artifacts
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.ARTIFACT_UPLOAD_AWS_ROLE }}
role-session-name: "artifact-upload-${{ github.run_number }}"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
role-duration-seconds: 900
- name: Upload artifacts to S3
working-directory: ${{ env.ARTIFACT_DIRECTORY }}
env:
ARTIFACT_BUCKET: ${{ vars.ARTIFACT_SOURCE_BUCKET }}
ARTIFACT_VERSION: ${{ needs.setup.outputs.version }}
run: aws s3 cp . "s3://$ARTIFACT_BUCKET/teleport-plugins/tag/$ARTIFACT_VERSION/" --recursive
# Container artifacts
- name: Assume AWS role for pushing the container images
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.CONTAINER_IMAGE_UPLOAD_AWS_ROLE }}
role-session-name: "container-image-upload-${{ github.run_number }}"
role-duration-seconds: 900
- name: Authenticate with ECR
env:
CONTAINER_IMAGE_PRIVATE_REGISTRY: ${{ vars.CONTAINER_IMAGE_PRIVATE_REGISTRY }}
run: |
aws ecr get-login-password | docker login -u="AWS" --password-stdin "$CONTAINER_IMAGE_PRIVATE_REGISTRY"
- name: Build and push the container images
env:
CONTAINER_IMAGE_PRIVATE_REGISTRY: ${{ vars.CONTAINER_IMAGE_PRIVATE_REGISTRY }}
run: |
# Access plugins and event handler
make DOCKER_PRIVATE_REGISTRY="$CONTAINER_IMAGE_PRIVATE_REGISTRY" \
docker-push-access-all docker-push-event-handler
168 changes: 164 additions & 4 deletions .github/workflows/tag-publish.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,170 @@
---
name: Publish release

on:
workflow_dispatch:
workflow_dispatch:
inputs:
artifact-tag:
description: "The tag associated with the artifact to deploy (eg. v1.2.3)."
type: string
required: true
environment:
description: "The publishing environment that the workflow should run in."
type: environment
required: true
camscale marked this conversation as resolved.
Show resolved Hide resolved
# This is a workaround so that the actor who initiated a workflow run via a workflow dispatch event can determine the run ID of the started workflow run
workflow-tag:
description: "This field adds the provided value to a run step, allowing the calling actor to associate the started run with the GHA run ID."
type: string
required: false
release:
types:
- released # This may need to be changed to "published"
fheinecke marked this conversation as resolved.
Show resolved Hide resolved

concurrency: "Limit to one build at a time for artifact tag ${{ inputs.artifact-tag || github.event.release.tag_name }}"

jobs:
placeholder:
publish:
runs-on: ubuntu-latest
# Unfortuntely this cannot be set as a global env var as they are not evaluated until runtime
environment: ${{ inputs.environment || 'release-prod' }}
permissions:
id-token: write
env:
ARTIFACT_TAG: ${{ inputs.artifact-tag || github.event.release.tag_name }}
LOCAL_ARTIFACTS_PATH: /tmp/artifacts
LOCAL_HELM_REPO_PATH: /tmp/helm-repo
LOCAL_TERRAFORM_REGISTRY_PATH: /tmp/terraform-registry
ENVIRONMENT_NAME: ${{ inputs.environment || 'release-prod' }}
steps:
- run: echo "Placeholder"
- name: Validate artifact tag
env:
SEMVER_REGEX: ^v?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?:[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
run: |
(echo "$ARTIFACT_TAG" | grep -qP "$SEMVER_REGEX") || (echo "The artifact tag $ARTIFACT_TAG is not a valid semver-coerced value"; exit 1)
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
- name: Validate environment
run: |
(echo "$ENVIRONMENT_NAME" | grep -qP '^publish-(prod|stage)$') || (echo "This workflow may only be ran from publishing environments"; exit 1)
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ github.workflow_sha }} # Publishing tooling should all be the same version
- name: Setup tooling Go
uses: actions/setup-go@v5
with:
go-version-file: "./tooling/go.mod"
cache-dependency-path: "./tooling/go.sum"
check-latest: true
# Sync artifacts down (required by everything)
- name: Assume AWS role for uploading the artifacts
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.ARTIFACT_DOWNLOAD_AWS_ROLE }}
role-session-name: "artifact-download-${{ github.run_number }}"
role-duration-seconds: 900
- name: Download artifacts from S3
env:
ARTIFACT_BUCKET: ${{ vars.ARTIFACT_SOURCE_BUCKET }}
run: aws s3 cp "s3://$ARTIFACT_BUCKET/teleport-plugins/tag/$ARTIFACT_TAG/" "$LOCAL_ARTIFACTS_PATH" --recursive
# Binary artifact promotion
- name: Assume AWS role for uploading the artifacts
# This step is only supported in production as there is no staging version of Houston
if: ${{ env.ENVIRONMENT_NAME == 'publish-prod' }}
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.HOUSTON_UPLOAD_AWS_ROLE }}
role-session-name: "houston-upload-${{ github.run_number }}"
role-duration-seconds: 900
- name: Upload artifacts to Houston
# This step is only supported in production as there is no staging version of Houston
if: ${{ env.ENVIRONMENT_NAME == 'publish-prod' }}
camscale marked this conversation as resolved.
Show resolved Hide resolved
env:
HOUSTON_BUCKET: ${{ vars.HOUSTON_BUCKET }}
run: |
aws s3 sync --acl public-read "$LOCAL_ARTIFACTS_PATH" s3://$HOUSTON_BUCKET/teleport-plugins/${ARTIFACT_TAG##*-v}/ \
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
--include "*" \
--exclude "*.tgz*" # Exclude helm chart artifacts
# Image promotion
- name: Assume AWS role for publishing the container images
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.CONTAINER_IMAGE_PUBLISHING_SYNC_AWS_ROLE }}
role-session-name: "container-image-publishing-sync-${{ github.run_number }}"
role-duration-seconds: 900
- name: Authenticate with ECR
env:
CONTAINER_IMAGE_PRIVATE_REGISTRY: ${{ vars.CONTAINER_IMAGE_PRIVATE_REGISTRY }}
run: |
aws ecr get-login-password | docker login -u="AWS" --password-stdin "$CONTAINER_IMAGE_PRIVATE_REGISTRY"
aws ecr-public get-login-password --region us-east-1 | docker login -u="AWS" --password-stdin public.ecr.aws
- name: Publish access and event-handler images
env:
CONTAINER_IMAGE_PRIVATE_REGISTRY: ${{ vars.CONTAINER_IMAGE_PRIVATE_REGISTRY }}
CONTAINER_IMAGE_PUBLIC_REGISTRY: ${{ vars.CONTAINER_IMAGE_PUBLIC_REGISTRY}}
GITREF: ${{ env.ARTIFACT_TAG }}
run: |
export VERSION=${ARTIFACT_TAG##v}
make -j"$(nproc)" DOCKER_PRIVATE_REGISTRY="$CONTAINER_IMAGE_PRIVATE_REGISTRY" \
DOCKER_ECR_PUBLIC_REGISTRY="$CONTAINER_IMAGE_PUBLIC_REGISTRY" docker-promote
# Helm promotion
- name: Assume AWS role for syncing the Helm artifacts
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.HELM_PUBLISHING_SYNC_AWS_ROLE }}
role-session-name: "helm-publishing-sync-${{ github.run_number }}"
role-duration-seconds: 900
- name: Download the Helm repo from S3
env:
HELM_REPO_BUCKET: ${{ vars.HELM_REPO_BUCKET }}
run: aws s3 cp "s3://$HELM_REPO_BUCKET/" "$LOCAL_HELM_REPO_PATH" --recursive
- name: Copy the Helm charts to the repo and regenerate the index
working-directory: "${{ env.LOCAL_HELM_REPO_PATH }}"
run: |
cp $(find "$LOCAL_ARTIFACTS_PATH" -name "teleport-plugin-*.tgz" -type f) .
fheinecke marked this conversation as resolved.
Show resolved Hide resolved
helm repo index .
- name: Upload the Helm repo to S3
env:
HELM_REPO_BUCKET: ${{ vars.HELM_REPO_BUCKET }}
run: aws s3 sync "$LOCAL_HELM_REPO_PATH" "s3://$HELM_REPO_BUCKET/"
# Terraform promotion
- name: Assume AWS role for syncing the Terraform artifacts
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-skip-session-tagging: true
aws-region: us-west-2
role-to-assume: ${{ vars.TERRAFORM_PUBLISHING_SYNC_AWS_ROLE }}
role-session-name: "terraform-publishing-sync-${{ github.run_number }}"
role-duration-seconds: 900
- name: Download the Terraform repo from S3
env:
TERRAFORM_REGISTRY_BUCKET: ${{ vars.TERRAFORM_REGISTRY_BUCKET }}
run: aws s3 cp "s3://$TERRAFORM_REGISTRY_BUCKET/" "$LOCAL_TERRAFORM_REGISTRY_PATH" --recursive
- name: Run the terraform-publish tool
env:
TERRAFORM_REGISTRY_URL: ${{ vars.TERRAFORM_REGISTRY_URL }}
SIGNING_KEY: ${{ secrets.TERRAFORM_SIGNING_KEY }}
run: |
go run -C tooling ./cmd/promote-terraform \
--tag "$ARTIFACT_TAG" \
--artifact-directory-path "$LOCAL_ARTIFACTS_PATH" \
--registry-directory-path "$LOCAL_TERRAFORM_REGISTRY_PATH" \
--protocol 6 \
--registry-url "$TERRAFORM_REGISTRY_URL" \
--namespace gravitational \
--name teleport
- name: Upload the Terraform repo to S3
env:
TERRAFORM_REGISTRY_BUCKET: ${{ vars.TERRAFORM_REGISTRY_BUCKET }}
run: aws s3 sync "$LOCAL_TERRAFORM_REGISTRY_PATH" "s3://$TERRAFORM_REGISTRY_BUCKET/"
- name: ${{ inputs.workflow-tag }}
if: inputs.workflow-tag != ''
run: |
# Do nothing

Loading
Loading