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
234 changes: 234 additions & 0 deletions .github/workflows/k8s-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
name: Deploy K8s Preview

on:
pull_request:
branches: [ develop ]
types: [ opened, reopened, synchronize ]
push:
branches: [ develop ]

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

DOCKER_REGISTRY: ghcr.io
DOCKER_PACKAGE: site-composite

KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_BASE64 }}
KUBE_NAMESPACE: code-for-philly
KUBE_HOSTNAME: codeforphilly.sandbox.k8s.phl.io

DATABASE_NAME: codeforphilly

HAB_LICENSE: accept-no-persist
HAB_ORIGIN: codeforphilly

jobs:

k8s-deploy:
runs-on: ubuntu-latest
steps:

- name: Cancel superseded runs
uses: styfle/cancel-workflow-action@0.7.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}

- name: Configure environment
run: |
if [ "${GITHUB_EVENT_NAME}" == "pull_request" ]; then
RELEASE_NAME="pr-$(jq --raw-output .pull_request.number "${GITHUB_EVENT_PATH}")"
RELEASE_TRANSIENT='true'
else
RELEASE_NAME="latest"
RELEASE_TRANSIENT='false'
fi

echo "Using RELEASE_NAME=${RELEASE_NAME}"
echo "RELEASE_NAME=${RELEASE_NAME}" >> $GITHUB_ENV

echo "Using RELEASE_TRANSIENT=${RELEASE_TRANSIENT}"
echo "RELEASE_TRANSIENT=${RELEASE_TRANSIENT}" >> $GITHUB_ENV

DOCKER_REPOSITORY="${GITHUB_REPOSITORY,,}"

echo "Using DOCKER_REPOSITORY=${DOCKER_REPOSITORY}"
echo "DOCKER_REPOSITORY=${DOCKER_REPOSITORY}" >> $GITHUB_ENV

- name: Create Github Deployment
uses: bobheadxi/deployments@v0.4.3
id: deployment
with:
step: start
token: ${{ secrets.GITHUB_TOKEN }}
env: '${{ env.RELEASE_NAME }}'
ref: '${{ github.head_ref }}'
transient: ${{ env.RELEASE_TRANSIENT }}
logs: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
no_override: false

- uses: actions/checkout@v2

- name: 'Initialize Chef Habitat environment'
uses: JarvusInnovations/habitat-action@action/v1
with:
deps: |
jarvus/hologit

- id: site-projection
name: 'Project holobranch: emergence-site'
uses: JarvusInnovations/hologit@actions/projector/v1
with:
# use HEAD checked out above by checkout action
ref: HEAD
fetch: false
holobranch: emergence-site

- id: fixtures-projection
name: 'Project holobranch: fixtures'
uses: JarvusInnovations/hologit@actions/projector/v1
with:
# use HEAD checked out above by checkout action
ref: HEAD
fetch: false
holobranch: fixtures

- id: helm-projection
name: 'Project holobranch: helm-chart'
uses: JarvusInnovations/hologit@actions/projector/v1
with:
# use HEAD checked out above by checkout action
ref: HEAD
fetch: false
holobranch: helm-chart

- name: Build & push Docker image
uses: whoan/docker-build-with-cache-action@v5
with:
dockerfile: Dockerfile
username: ${{ github.actor }}
password: ${{ env.GITHUB_TOKEN }}
registry: ${{ env.DOCKER_REGISTRY }}
image_name: ${{ env.DOCKER_REPOSITORY }}/${{ env.DOCKER_PACKAGE }}
image_tag: ${{ env.RELEASE_NAME }}
build_extra_args: |
--build-arg=SITE_TREE=${{ steps.site-projection.outputs.tree }}
--build-arg=SITE_VERSION=0.0.0-${{ env.RELEASE_NAME }}
--build-arg=SOURCE_COMMIT=${{ github.sha }}
--build-arg=SOURCE_TAG=${{ env.RELEASE_NAME }}
--build-arg=HAB_LICENSE=${{ env.HAB_LICENSE }}

- name: Configure kubectl
run: |
set -e
test -e ~/.kube || mkdir ~/.kube
printf '%s' "$KUBE_CONFIG_DATA" | base64 -d > ~/.kube/config

- name: Deploy instance via Helm template
run: |
release_hostname="${RELEASE_NAME}.${KUBE_HOSTNAME}"

echo "Ensuring current context is namespace ${KUBE_NAMESPACE}"
kubectl config set-context --current --namespace="${KUBE_NAMESPACE}"

echo "Listing pods existing before deploy"
kubectl get pods \
-l app.kubernetes.io/instance="${RELEASE_NAME}" \
--template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' \
| sort \
| tee ./.pods-before

echo "Extracting projected helm-chart to temporary directory"
temp_dir=$(mktemp -d)
git archive --format=tar "${{ steps.helm-projection.outputs.tree }}" | ( cd "${temp_dir}" && tar -xf - )

echo "Using helm upgrade to apply helm-chart to release ${RELEASE_NAME}"
helm upgrade "${RELEASE_NAME}" "${temp_dir}" \
--install \
--namespace "${KUBE_NAMESPACE}" \
--set site.name="${RELEASE_NAME}" \
--set site.title="laddr/${RELEASE_NAME}" \
--set site.image.repository="${DOCKER_REGISTRY}/${DOCKER_REPOSITORY}/${DOCKER_PACKAGE}" \
--set site.image.tag="${RELEASE_NAME}" \
--set ingress.enabled=true \
--set site.canonicalHostname="${release_hostname}" \
--set site.displayErrors=true \
--set hab.license=accept-no-persist

echo "Listing pods existing after deploy"
kubectl get pods \
-l app.kubernetes.io/instance="${RELEASE_NAME}" \
--template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' \
| sort \
| tee ./.pods-after

echo "Deleting stale pods to force image refresh"
comm -12 ./.pods-before ./.pods-after \
| xargs --no-run-if-empty kubectl delete pod

- name: Wait for Deployment to be ready
timeout-minutes: 10
run: |
until kubectl rollout status deployment "${RELEASE_NAME}" 2>/dev/null >/dev/null; do
echo -n "."
sleep .5
done

- name: Find new Pod
run: |
POD_NAME=$(
kubectl get pod \
-l app.kubernetes.io/instance="${RELEASE_NAME}" \
-o jsonpath='{.items[0].metadata.name}'
)

echo "Using POD_NAME=${POD_NAME}"
echo "POD_NAME=${POD_NAME}" >> $GITHUB_ENV

- name: Wait For Pod to be ready
timeout-minutes: 5
run: kubectl wait --for condition=ready "pod/${POD_NAME}" --timeout=30s

- name: Wait for MySQL to be Ready
timeout-minutes: 5
run: |
until kubectl exec "${POD_NAME}" -- hab pkg exec "${HAB_ORIGIN}/${DOCKER_PACKAGE}" mysqladmin ping; do
sleep .5
done

- name: Load fixtures into database
run: |
echo "Dropping any existing database..."
kubectl exec "${POD_NAME}" -- \
hab pkg exec "${HAB_ORIGIN}/${DOCKER_PACKAGE}" \
mysqladmin drop "${DATABASE_NAME}" --force \
|| true

echo "Creating an empty database..."
kubectl exec "${POD_NAME}" -- \
hab pkg exec "${HAB_ORIGIN}/${DOCKER_PACKAGE}" \
mysqladmin create "${DATABASE_NAME}"

echo "Loading fixtures..."
(
for fixture_file in $(git ls-tree -r --name-only ${{ steps.fixtures-projection.outputs.tree }}); do
git cat-file -p "${{ steps.fixtures-projection.outputs.tree }}:${fixture_file}"
done
) | kubectl exec -i "${POD_NAME}" -- \
hab pkg exec "${HAB_ORIGIN}/${DOCKER_PACKAGE}" \
mysql "${DATABASE_NAME}"

echo "Running migrations..."
kubectl exec "${POD_NAME}" -- \
hab pkg exec "${HAB_ORIGIN}/${DOCKER_PACKAGE}" \
emergence-console-run migrations:execute --all

- name: Update Github Deployment
uses: bobheadxi/deployments@v0.4.3
if: ${{ always() }}
with:
step: finish
token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
env_url: 'https://${{ env.RELEASE_NAME}}.${{ env.KUBE_HOSTNAME }}/'
logs: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
38 changes: 38 additions & 0 deletions .github/workflows/k8s-destroy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Destroy K8s Preview

on:
pull_request:
branches: [ develop ]
types: [ closed ]

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_BASE64 }}
KUBE_NAMESPACE: code-for-philly

RELEASE_NAME: pr-${{ github.event.number }}

jobs:

k8s-destroy:
runs-on: ubuntu-latest
steps:

- name: Configure kubectl
run: |
test -e ~/.kube || mkdir ~/.kube
printf '%s' "$KUBE_CONFIG_DATA" | base64 -d > ~/.kube/config

- name: Delete PR Deployment
run: |
kubectl config set-context --current --namespace="${KUBE_NAMESPACE}"
kubectl delete deployment,replicaset,ingress,all -l "app.kubernetes.io/instance=${RELEASE_NAME}"
kubectl delete secret "${RELEASE_NAME}-tls"

- name: Deactivate Github Deployment
uses: bobheadxi/deployments@v0.4.3
with:
step: deactivate-env
token: ${{ secrets.GITHUB_TOKEN }}
env: '${{ env.RELEASE_NAME }}'
2 changes: 1 addition & 1 deletion .holo/sources/laddr.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[holosource]
url = "https://github.com/CodeForPhilly/laddr"
ref = "refs/tags/v3.0.3"
ref = "refs/tags/v3.0.5"
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ RUN hab pkg exec core/hab-plan-build hab-plan-build /src/habitat/composite
FROM habitat as runtime

# configure persistent volumes
RUN hab pkg exec core/coreutils mkdir -p '/hab/svc/mysql/data' '/hab/svc/codeforphilly/data' '/hab/svc/nginx/files' \
&& hab pkg exec core/coreutils chown hab:hab -R '/hab/svc/mysql/data' '/hab/svc/codeforphilly/data' '/hab/svc/nginx/files'
RUN hab pkg exec core/coreutils mkdir -p '/hab/svc/mysql/data' '/hab/svc/site/data' '/hab/svc/nginx/files' \
&& hab pkg exec core/coreutils chown hab:hab -R '/hab/svc/mysql/data' '/hab/svc/site/data' '/hab/svc/nginx/files'

# configure entrypoint
VOLUME ["/hab/svc/mysql/data", "/hab/svc/codeforphilly/data", "/hab/svc/nginx/files"]
VOLUME ["/hab/svc/mysql/data", "/hab/svc/site/data", "/hab/svc/nginx/files"]
ENTRYPOINT ["hab", "sup", "run"]
CMD ["codeforphilly/codeforphilly-composite"]
CMD ["codeforphilly/site-composite"]

# install .hart artifact from builder stage
COPY --from=projector /hab/cache/artifacts/$HAB_ORIGIN-* /hab/cache/artifacts/
Expand Down
2 changes: 1 addition & 1 deletion habitat/composite/plan.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
composite_app_pkg_name=codeforphilly
composite_app_pkg_name=site
pkg_name="${composite_app_pkg_name}-composite"
pkg_origin=codeforphilly
pkg_maintainer="Code for Philly <hello@codeforphilly.org>"
Expand Down
2 changes: 1 addition & 1 deletion habitat/plan.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pkg_name=codeforphilly
pkg_name=site
pkg_origin=codeforphilly
pkg_maintainer="Code for Philly <hello@codeforphilly.org>"
pkg_scaffolding=emergence/scaffolding-site
Expand Down