Repository navigation
Patch/feat/GitHub actions cicd - #165
Conversation
| - ".gitignore" | ||
| - ".env/**" | ||
| push: | ||
| branches: [master] |
There was a problem hiding this comment.
You can add your test/current branch here in order to test the run.
There was a problem hiding this comment.
Hi @VinneyJ I isolated the the testing and the workflow passed for staging. I will share for production. Merging the patch to other PR branch will trigger the workflow and you'll be able to see it in action. PS. Your worflow version had secrets.DOKKU_HOST_KEY which needs to be added to each environment.
|
@VinneyJ Production deploy dispatch simulation works now for an app that was never deployed before. This is a separate nginx issue that will be addressed. However, since sensors prod has been deployed before and nginx configurations exist, the workflow will dispatch without any issues.
|
| - staging | ||
| - production | ||
| default: staging | ||
| image_tag: # prevent production deployment from using a PR image tag with manual workflow_dispatch trigger |
There was a problem hiding this comment.
For the manual deployment, may need to validate the tags such as:
beta-pr-123-abcd1234, pr-123, latest, random-tag
So validation guard would help minimize this. A gurad like this:
guard:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-22.04
steps:
- name: Validate manual deployment
env:
DEPLOY_ENVIRONMENT: ${{ inputs.environment }}
IMAGE_TAG: ${{ inputs.image_tag }}
run: |
set -euo pipefail
if [[ "$DEPLOY_ENVIRONMENT" == "production" &&
"$GITHUB_REF" != "refs/heads/master" ]]; then
echo "Production deployment is only allowed from master" >&2
exit 1
fi
if [[ "$DEPLOY_ENVIRONMENT" == "production" &&
! "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Production requires a release tag such as v1.4.2" >&2
exit 1
fi
There was a problem hiding this comment.
I see the need here but doesn't this bring us back to verbosity which we were avoiding in the first place @VinneyJ . Can we avoid this by creating a ruleset for allowed actors to perform the manual dispatch?
| (needs.build-and-push.result == 'success' || needs.build-and-push.result == 'skipped') | ||
| runs-on: ubuntu-latest | ||
| environment: ${{ github.event_name == 'workflow_dispatch' && inputs.environment || (github.event_name == 'pull_request' && 'staging' || 'production') }} | ||
| env: |
There was a problem hiding this comment.
We can use an environment-specific HEALTHCHECK_URL variable to verify the health of the application and detect a broken deployment. So, something like:
env:
DOKKU_HOST: ${{ vars.DOKKU_HOST }}
DOKKU_APP: ${{ vars.DOKKU_APP }}
HEALTHCHECK_URL: ${{ vars.HEALTHCHECK_URL }}
IMAGE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.image_tag || needs.build-and-push.outputs.image-tag }}
and finally:
- name: Verify deployment
run: |
set -euo pipefail
for attempt in {1..12}; do
echo "Health check attempt $attempt"
if curl \
--fail \
--silent \
--show-error \
--max-time 10 \
"$HEALTHCHECK_URL"; then
echo "Deployment is healthy"
exit 0
fi
sleep 10
done
echo "Deployment failed its health check" >&2
exit 1
We can configure HEALTHCHECK_URL separately in the staging and production Environments.
There was a problem hiding this comment.
@VinneyJ I am trying to understand why we need a health check report when Dokku itself has zero-downtime deploy checks built in. Also, if the health check fails, exit 1 fails the entire deploy job and by that time, Dokku will have swapped traffic to the new broken container.
|
You can amend those 2 and then I will improve the pipeline later after the merge by adding immutability(because right now we are building the image twice for staging and prod while we can just reuse the staging image) to the deployment and production protection. @gideonmaina |
|
Glad to see we're doing CI/CD but:
I'm not saying you shouldn't support manual deployment. If that's really needed, it should be in addition to the 2 approaches above and not a replacement. |
|
@kilemensi I will try out the Dokku Github Actions. I'm sure it will be simpler/leaner that this. I'll see what I can patch here later especially the About the manual deployment. From my observation, a merged PR on master will automatically trigger a production deployment with the latest image semantic version. A manual trigger could be useful if a roll-back is necessary. Also what do you think about having an extra Health Check step in the workflow when this can be set via |
|
Thanks @gideonmaina
I hear you but a merged PR should automatically deploy to STAGING and not PROD. Deploying to PROD should be triggered after reviewing and confirming all is good on STAGING. The actual PROD deployment should be triggered by some version bump either in the project file or via git tags (or both). This way, the question of what version is running in PROD can be answered by just checking git. Even if you have to rollback, you undo the broken commits first and bump version again to trigger fix deployment to PROD (after confirming the fix works in STAGING). ... having said all of that, it's OK if we have manual deployment, but as I said, that should be in addition to the automated ways and we should strive for full automated deployments i.e. actual CI/CD.
That's what the checks are there for. If there is a check that can add confidence to the deployments, lets do. ... but, and I know I sound like a broken record at this point, a proper rethink of sensors.AFRICA architecture makes more sense to me than any little improvements we can do here and there around the current architecture. We need an architecture that includes observability as first class citizen i.e. metrics (gauge, counters, etc.) and logs, protection and isolation of sensitive paths e.g. the data ingestion endpoint, security and AAA across other endpoints, proper use of time-series database extensions, etc. A decade is a very longtime in tech and I believe the current architecture is at least 10 years old. |
|
Thanks for the feedback @kilemensi . I will rework the pipeline so master merges auto-deploy to STAGING only, with PROD gated on a version bump (tag/file, or both) ; though I think the logic will be similar in the sense that merging a PR should only happen when STAGING deployments are satisfactory. @VinneyJ we can handle this on another issue to move things quicker, if that's okay with you, alongside the health check to determine which gives us the best guarantee. On the architecture rethink, I totally agree with the gaps you've flagged. My concern is capacity. Reviews already take a while to land and largely dependent on support from outside our team (internally, we're stretched thin on technical depth right now to speed things up). A full rework is something I would happy to drive but I am not confident I can take it on well solo alongside the scope I'm already filling without the tech team's full support beyond review bandwith. |
* Add workflow to push to dokku * Ensure separate version tagging for prs and deploy versions Reads and bumps from VERSION file for prod deploy * Bump image version from Dockerhub Cleaner than reading VERSION file. TODO: update to accomadate major version releases * Scope pip versions to below 24 Resolves Celery 4.3.0 package dependency * Add missing dateutil module * Downgrade ubuntu and pyhthon versions. Add missing feinstaub module * [test CI] feat: add create method to NodesView View had missing ViewSet section * [test CI] fix: rewrite cache_lastactive_nodes raw SQL to Django ORM * [test CI] fix: update tests for SQLite/PostgreSQL dual compatibility - Makes test database configurable via SENSORSAFRICA_TEST_DATABASE_URL env var, defaulting to SQLite - Adds pytest_collection_modifyitems hook to auto-skip @pytest.mark.postgres_only tests on SQLite - Registers the postgres_only marker in pytest.ini - Updates v2 tests to authenticate via token and use correct /v2/data/stats/air/ URLs - Marks deprecated v1 tests (test_filter_view, test_sensordata_view, test_sensor_view) as skipped - Marks PostgreSQL-dependent stats tests as @pytest.mark.postgres_only - Fixes bulk_create re-fetch for SQLite (which doesn't return PKs in Django 1.11) * [test CI] chore: add PostgreSQL service to CI and document test setup * fix: update all runner images from deprecated ubuntu-20.04 to ubuntu-22.04 * fix: bump CI Python version from 3.6 to 3.7 (not available on ubuntu-22.04) * fix: install feinstaub with --no-deps to avoid opbeat build failure on Python 3.7 * fix: pre-install binary-compatible gevent/greenlet wheels for Python 3.7 * fix: pin importlib-metadata for compatibility with old pytest * fix: lazy-load django.conf.settings inside pytest hook to avoid ImproperlyConfigured * fix: lazy-load all Django imports inside fixtures to fix ImproperlyConfigured on CI * fix: use env var instead of Django settings in pytest_collection_modifyitems hook * fix: add djangorestframework and other feinstaub core deps dropped by --no-deps * fix: lazy-load all Django/DRF imports inside test methods to avoid ImproperlyConfigured * fix: add pytest-django to requirements.txt and set DJANGO_SETTINGS_MODULE env in CI * fix: add missing lazy imports for APIRequestFactory and views/models in test methods * Create dockerhub repo if missing * fix: dokku from image * Fix dokku command and ensure app exists before pull from image * fix: use workflow-level IMAGE_NAME in deploy jobs * check non-empty env guard rail pre dokku build * fix: add setup-python 3.7 and full deps to integration-tests job * fix: correct test path to sensorsafrica/tests in integration-tests * refactor: consolidate all deps into requirements.txt, simplify CI install step * Patch/feat/GitHub actions cicd (#165) * Remove integration-test job * Refactor: Simpler deploy job * Worfklow dispatch: image tag input * Add guard rail to trigger manual dispatch from master only * Config GA concurrency and permission * Add deploy logic with guard job required * clean worflow and fix missing deploy repo name * Validate semantic version image tag for manual production deployment

Description
This PR is a patch to PR #162 in an aim to make the workflow leaner by reducing verbosity
Additional changes.
DOCKERHUB_REPOname in dokku deploy command.beta-pr-. i.e. only deploy from master refs.Potential changes
testjob in its own worflow