Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve nightly build and deployment logic #3164

Merged
merged 33 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
06fda97
Update release.yml
zaneselvans Dec 18, 2023
97a6089
Tag commits of nightly builds and last stable release.
zaneselvans Dec 15, 2023
e83334e
Test pushing a tag in a GitHub action
zaneselvans Dec 18, 2023
7cc0f18
Add email and name to git user before pushing tag.
zaneselvans Dec 18, 2023
ebb594b
Change envvar syntax to capture date in tag.
zaneselvans Dec 18, 2023
b0f218e
Push tag first, go faster.
zaneselvans Dec 18, 2023
9c597e9
Try to fix nightly tag workflow
zaneselvans Dec 18, 2023
1171321
Try to fix nightly tag workflow
zaneselvans Dec 18, 2023
f42e951
Set up nightly tag in deploy workflow.
zaneselvans Dec 18, 2023
736476e
Use git commands to tag stable during release.
zaneselvans Dec 18, 2023
afc25af
Purge old files from distribution path before uploading new files.
zaneselvans Dec 19, 2023
273d173
Apply nightly-YYYY-MM-DD to GIHUB_REF not main
zaneselvans Dec 19, 2023
fa0c044
Try to tag nightly from within docker container
zaneselvans Dec 19, 2023
fe5e224
Make nightly & stable branches. Safer removal of old deployments. Rel…
zaneselvans Dec 20, 2023
b68bb63
Copy repo contents into container before building conda env.
zaneselvans Dec 20, 2023
eef0c62
Attempt to clone repo inside Docker container
zaneselvans Dec 20, 2023
c0f1be7
Attempt to clone repo inside Docker container
zaneselvans Dec 20, 2023
bf02f01
Attempt to clone repo inside Docker container
zaneselvans Dec 20, 2023
f225532
Attempt to clone repo inside Docker container
zaneselvans Dec 20, 2023
8892f39
Attempt to clone repo inside Docker container
zaneselvans Dec 20, 2023
85e9449
Attempt to clone repo inside Docker container
zaneselvans Dec 20, 2023
16445d4
Revert to copying repo into container
zaneselvans Dec 20, 2023
ddfb861
Move pudl repo into the pudl/ directory
zaneselvans Dec 20, 2023
9f98de6
Stop using conda run when not required.
zaneselvans Dec 20, 2023
b3b3f52
Try and do a git thing
zaneselvans Dec 20, 2023
f989635
Test git authentication with workflow_dispatch
zaneselvans Dec 20, 2023
5f1228b
Add some logging to git authentication check
zaneselvans Dec 20, 2023
b457942
Update settings file path to point at repo in container
zaneselvans Dec 20, 2023
03f6e19
unset read-only git config
zaneselvans Dec 20, 2023
f409d8d
Consolidate envvars and set explicit BUILD_ID
zaneselvans Dec 20, 2023
ac31f1e
Clean up GCP PUDL ETL script
zaneselvans Dec 20, 2023
2e6097c
remove old ACTION_SHA add BUILD_ID to container envvars
zaneselvans Dec 20, 2023
de58851
Reinstate caching of conda environment in Docker image.
zaneselvans Dec 20, 2023
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
17 changes: 17 additions & 0 deletions .github/release.yml
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
changelog:
exclude:
authors:
- dependabot
- pre-commit-ci
- pudlbot
labels:
- conda-lock
- dependencies
categories:
- title: New Data
labels:
- new-data
- title: Other Changes
labels:
- "*"
24 changes: 18 additions & 6 deletions .github/workflows/build-deploy-pudl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,22 @@ jobs:
if: ${{ (github.event_name == 'schedule') }}
run: |
echo "This action was triggered by a schedule." && echo "GCE_INSTANCE=pudl-deployment-dev" >> $GITHUB_ENV && echo "GITHUB_REF=dev" >> $GITHUB_ENV
echo "NIGHTLY_TAG=nightly-$(date +%Y-%m-%d)" >> $GITHUB_ENV
echo "NIGHTLY_TAG: $NIGHTLY_TAG"

- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ env.GITHUB_REF }}

- name: Tag nightly build
if: ${{ (github.event_name == 'schedule') }}
run: |
git config user.email "[email protected]"
git config user.name "PudlBot"
git tag -a -m "$NIGHTLY_TAG" $NIGHTLY_TAG $GITHUB_REF
git push origin $NIGHTLY_TAG

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is doing what we want it to now. It's a tag, it's applied to the branch that we're going to build (not main which is checked out here).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet! Just to get this straight: we are tagging whatever this build gets kicked off on. Since this only triggers on schedule, and GITHUB_REF gets munged to dev in that case, we will always be tagging whatever the latest dev is with nightly-build-202x-xx-xx.

And then, when the nightly build succeeds, we can tell the nightly branch to point at nightly-build-202x-xx-xx and everyone who downloads the most recent nightly build off AWS will know that that corresponds to the nightly branch. But if they want to download nightly-build-202x-xx-xx from AWS they will also be able to associate that with the nightly-build-202x-xx-xx tag.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's close, except that we only distribute the most recent nightly build and tagged releases to AWS. I imagine we would also have a copy of the most recent release in a stable/ directory. So if you want to refer to nightly-202x-xx-xx you would need to look at the gs://builds.catalyst.coop/nightly-202x-xx-xx path where the last 30 days of nightly build outputs are stashed, regardless of whether they were successful or not. So if you want to look at nightly build outputs + the code that generated them, you can look at the GCS output, and the tagged commit that matches its name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right - that makes sense! Are there any barriers to distributing a few recent nightly builds on AWS as well as GCS?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a limited storage quota on AWS, and I don't think we actually want the public looking at our nightly build outputs, which may or or may not correspond to successful runs.

- name: Get HEAD of the branch (main or dev)
run: |
echo "ACTION_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
Expand All @@ -45,7 +55,7 @@ jobs:

- name: Docker Metadata
id: docker_metadata
uses: docker/metadata-action@v5.3.0
uses: docker/metadata-action@v5
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
with:
images: catalystcoop/pudl-etl
flavor: |
Expand All @@ -55,17 +65,17 @@ jobs:
type=ref,event=tag

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3.0.0
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build image and push to Docker Hub
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v5
with:
context: .
file: docker/Dockerfile
Expand Down Expand Up @@ -114,6 +124,7 @@ jobs:
--container-env-file="./docker/.env" \
--container-env ACTION_SHA=$ACTION_SHA \
--container-env GITHUB_REF=${{ env.GITHUB_REF }} \
--container-env NIGHTLY_TAG=${{ env.NIGHTLY_TAG }} \
--container-env GITHUB_ACTION_TRIGGER=${{ github.event_name }} \
--container-env SLACK_TOKEN=${{ secrets.PUDL_DEPLOY_SLACK_TOKEN }} \
--container-env GCE_INSTANCE=${{ env.GCE_INSTANCE }} \
Expand All @@ -127,8 +138,9 @@ jobs:
--container-env DAGSTER_PG_HOST="104.154.182.24" \
--container-env DAGSTER_PG_DB="dagster-storage" \
--container-env FLY_ACCESS_TOKEN=${{ secrets.FLY_ACCESS_TOKEN }} \
--container-env PUDL_BOT_PAT=${{ secrets.PUDL_BOT_PAT }} \
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
--container-env ZENODO_SANDBOX_TOKEN_PUBLISH=${{ secrets.ZENODO_SANDBOX_TOKEN_PUBLISH }} \
--container-env PUDL_SETTINGS_YML="/home/mambauser/src/pudl/package_data/settings/etl_full.yml" \
--container-env PUDL_SETTINGS_YML="/home/mambauser/pudl/src/pudl/package_data/settings/etl_full.yml" \
jdangerx marked this conversation as resolved.
Show resolved Hide resolved
--container-env PUDL_GCS_OUTPUT=${{ env.PUDL_OUTPUT_PATH }}

# Start the VM
Expand All @@ -137,7 +149,7 @@ jobs:

- name: Post to a pudl-deployments channel
id: slack
uses: slackapi/slack-github-action@v1.24.0
uses: slackapi/slack-github-action@v1
with:
channel-id: "C03FHB9N0PQ"
slack-message: "build-deploy-pudl status: ${{ job.status }}\n${{ env.GCS_OUTPUT_BUCKET }}/${{ env.RUN_TIMESTAMP}}-${{ env.SHORT_SHA }}-${{ env.COMMIT_BRANCH }}"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/docker-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ jobs:

- name: Docker Metadata
id: docker_metadata
uses: docker/metadata-action@v5.3.0
uses: docker/metadata-action@v5
with:
images: catalystcoop/pudl-etl
flavor: |
latest=auto

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0
uses: docker/setup-buildx-action@v3

- name: Build image but do not push to Docker Hub
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v5
with:
context: .
file: docker/Dockerfile
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
name: python-package-distributions
path: dist/
- name: Sign dist with Sigstore
uses: sigstore/gh-action-sigstore-python@v2.1.0
uses: sigstore/gh-action-sigstore-python@v2
with:
inputs: ./dist/*.tar.gz ./dist/*.whl
- name: Upload artifact signatures to GitHub Release
Expand All @@ -95,6 +95,13 @@ jobs:
--discussion-category Announcements
--generate-notes
--repo '${{ github.repository }}'
- name: Tag the current stable commit
run: |
git config user.email "[email protected]"
git config user.name "pudlbot"
git checkout stable
git merge --ff-only ${{ github.ref_name }}
git push
jdangerx marked this conversation as resolved.
Show resolved Hide resolved

notify-slack:
runs-on: ubuntu-latest
Expand Down
21 changes: 10 additions & 11 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mambaorg/micromamba:1.5.3
FROM mambaorg/micromamba:1.5.5

USER root

Expand Down Expand Up @@ -30,28 +30,27 @@ ENV PUDL_INPUT=${CONTAINER_PUDL_WORKSPACE}/input
ENV PUDL_OUTPUT=${CONTAINER_PUDL_WORKSPACE}/output
ENV DAGSTER_HOME=${CONTAINER_PUDL_WORKSPACE}/dagster_home

RUN mkdir -p ${PUDL_INPUT} ${PUDL_OUTPUT} ${DAGSTER_HOME}
RUN mkdir -p ${PUDL_INPUT} ${PUDL_OUTPUT} ${DAGSTER_HOME} ${PUDL_REPO}
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved

# Copy dagster configuration file
COPY docker/dagster.yaml ${DAGSTER_HOME}/dagster.yaml

# Copy the cloned pudl repository into the container
# This includes the .git directory, so it is a whole repo
COPY --chown=${MAMBA_USER}:${MAMBA_USER} . ${PUDL_REPO}

zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
# Create a conda environment based on the specification in the repo
COPY environments/conda-lock.yml environments/conda-lock.yml
RUN micromamba create --prefix ${CONDA_PREFIX} --yes --file environments/conda-lock.yml && \
RUN micromamba create --prefix ${CONDA_PREFIX} --yes --file ${PUDL_REPO}/environments/conda-lock.yml && \
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
micromamba clean -afy
# Copy the cloned pudl repository into the user's home directory
COPY --chown=${MAMBA_USER}:${MAMBA_USER} . ${CONTAINER_HOME}

# TODO(rousik): The following is a workaround for sudden breakage where conda
# can't find libraries contained within the environment. It's unclear why!
ENV LD_LIBRARY_PATH=${CONDA_PREFIX}/lib
# We need information from .git to get version with setuptools_scm so we mount that
# directory without copying it into the image.
RUN --mount=type=bind,source=.git,target=${PUDL_REPO}/.git \
${CONDA_RUN} pip install --no-cache-dir --no-deps --editable .
jdangerx marked this conversation as resolved.
Show resolved Hide resolved
RUN ${CONDA_RUN} pip install --no-cache-dir --no-deps --editable ${PUDL_REPO}
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved

# Install awscli2
# Change back to root because the install script needs access to /usr/local/aws-cli
# curl commands run within conda environment because curl is installed by conda.
USER root
RUN ${CONDA_RUN} bash -c 'curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && ./aws/install'
USER $MAMBA_USER
Expand All @@ -61,6 +60,6 @@ USER $MAMBA_USER
RUN ${CONDA_RUN} bash -c 'curl -L https://fly.io/install.sh | sh'
ENV PATH="${CONTAINER_HOME}/.fly/bin:$PATH"


WORKDIR ${PUDL_REPO}
jdangerx marked this conversation as resolved.
Show resolved Hide resolved
# Run the unit tests:
CMD ["micromamba", "run", "--prefix", "${CONDA_PREFIX}", "--attach", "''", "pytest", "test/unit"]
50 changes: 37 additions & 13 deletions docker/gcp_pudl_etl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,12 @@ function run_pudl_etl() {
}

function shutdown_vm() {
# Copy the outputs to the GCS bucket

upload_file_to_slack $LOGFILE "pudl_etl logs for $ACTION_SHA-$GITHUB_REF:"

# Shut down the vm instance when the etl is done.
echo "Shutting down VM."
# # Shut down the vm instance when the etl is done.
ACCESS_TOKEN=`curl \
ACCESS_TOKEN=$(curl \
jdangerx marked this conversation as resolved.
Show resolved Hide resolved
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
-H "Metadata-Flavor: Google" | jq -r '.access_token'`

-H "Metadata-Flavor: Google" | jq -r '.access_token')
curl -X POST -H "Content-Length: 0" -H "Authorization: Bearer ${ACCESS_TOKEN}" https://compute.googleapis.com/compute/v1/projects/catalyst-cooperative-pudl/zones/$GCE_INSTANCE_ZONE/instances/$GCE_INSTANCE/stop
}

Expand All @@ -68,19 +64,25 @@ function copy_outputs_to_gcs() {
}

function copy_outputs_to_distribution_bucket() {
echo "Copying outputs to GCP distribution bucket"
gsutil -m -u $GCP_BILLING_PROJECT cp -r "$PUDL_OUTPUT/*" "gs://pudl.catalyst.coop/$GITHUB_REF"

echo "Copying outputs to AWS distribution bucket"
aws s3 cp "$PUDL_OUTPUT/" "s3://pudl.catalyst.coop/$GITHUB_REF" --recursive
# Only attempt to update outputs if we have a real value of GITHUB_REF
if [ -n "$GITHUB_REF" ]; then
jdangerx marked this conversation as resolved.
Show resolved Hide resolved
echo "Removing old $GITHUB_REF outputs from GCP distributon bucket."
gsutil -m -u $GCP_BILLING_PROJECT rm -r "gs://pudl.catalyst.coop/$GITHUB_REF"
echo "Copying outputs to GCP distribution bucket"
gsutil -m -u $GCP_BILLING_PROJECT cp -r "$PUDL_OUTPUT/*" "gs://pudl.catalyst.coop/$GITHUB_REF"

echo "Removing old $GITHUB_REF outputs from AWS distributon bucket."
aws s3 rm "s3://pudl.catalyst.coop/$GITHUB_REF" --recursive
echo "Copying outputs to AWS distribution bucket"
aws s3 cp "$PUDL_OUTPUT/" "s3://pudl.catalyst.coop/$GITHUB_REF" --recursive
fi
}

function zenodo_data_release() {
echo "Creating a new PUDL data release on Zenodo."
~/devtools/zenodo/zenodo_data_release.py --publish --env sandbox --source-dir $PUDL_OUTPUT
}


function notify_slack() {
# Notify pudl-builds slack channel of deployment status
if [ $1 = "success" ]; then
Expand All @@ -97,6 +99,19 @@ function notify_slack() {
send_slack_msg "$message"
}

if [ "$GITHUB_ACTION_TRIGGER" = "workflow_dispatch" ]; then
echo "Deployed via workflow_dispatch, testing git authentication!"
# Remove the read-only authentication header
git config --unset http.https://github.com/.extraheader
git config user.email "[email protected]"
git config user.name "pudlbot"
git remote set-url origin "https://pudlbot:[email protected]/catalyst-cooperative/pudl.git"
git config -l
git tag -a -m "Nightly test tag" nightly-tag-test
git push origin nightly-tag-test
shutdown_vm
fi

# # Run ETL. Copy outputs to GCS and shutdown VM if ETL succeeds or fails
# 2>&1 redirects stderr to stdout.
run_pudl_etl 2>&1 | tee $LOGFILE
Expand All @@ -107,6 +122,15 @@ copy_outputs_to_gcs

# if pipeline is successful, distribute + publish datasette
if [[ $ETL_SUCCESS == 0 ]]; then
if [ $GITHUB_ACTION_TRIGGER = "schedule" ]; then
# Update the nightly branch to point at newly successful nightly build tag
git config user.email "[email protected]"
git config user.name "pudlbot"
git remote set-url origin https://pudlbot:[email protected]/catalyst-cooperative/pudl.git
git checkout nightly
git merge --ff-only $NIGHTLY_TAG
git push
fi
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
# Deploy the updated data to datasette
if [ $GITHUB_REF = "dev" ]; then
python ~/devtools/datasette/publish.py 2>&1 | tee -a $LOGFILE
zaneselvans marked this conversation as resolved.
Show resolved Hide resolved
Expand Down