Terminal commands for setting up a Code Engine webhook and example application repository
- IBM Cloud CLI installed.
- Github CLI client installed and authenticated.
- jq installed.
Set these variables first as they are used by the next round that we need to set:
export RESOURCE_GROUP=""
export GITHUB_USERNAME=""
export IBMCLOUD_REGION=""
export IBMCLOUD_API_KEY=""
Next we generate a random secret for our webhook, set our ICR endpoint, and set some project related prefixes so its easier to keep track of what is deployed:
export WEBHOOK_SECRET=$(uuidgen | tr '[:upper:]' '[:lower:]')
export PROJECT_PREFIX=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-z' | fold -w 4 | head -n 1)
export ICR_NAMESPACE="${PROJECT_PREFIX}-icr-ns"
export ICR_IMAGE="${PROJECT_PREFIX}-simpleflask"
export ICR_ENDPOINT="${IBMCLOUD_REGION%%-*}.icr.io"
If you already have the plugins installed you may be prompted to reinstall or update the plugins.
ibmcloud login --apikey "${IBMCLOUD_API_KEY}" -r "${IBMCLOUD_REGION}" -g "${RESOURCE_GROUP}"
ibmcloud plugin install code-engine container-registry
The cr login
command will use the already selected region. We then add a namespace and create a new variable for the ICR endpoint.
slight rant: This is one of the few ic plugins that does not support
--output json
and it is maddening.
ibmcloud cr region-set "${ICR_ENDPOINT}"
ibmcloud cr login
ibmcloud cr namespace-add "${ICR_NAMESPACE}"
With the region and resource group targeted we can move on to creating the following resources:
- Code Engine Project
- Code Engine Registry secret to pull images from ICR
- Code Engine Generic secret for our Function
ibmcloud ce project create --name "${PROJECT_PREFIX}-ce-proj"
ibmcloud ce secret create --name "${PROJECT_PREFIX}-icr-secret" --format registry --username iamapikey --password "${IBMCLOUD_API_KEY}" --email "iamuser@example.com" --server "private.${ICR_ENDPOINT}"
ibmcloud ce secret create --name "${PROJECT_PREFIX}-function-secret" --format generic --from-literal CE_APP="${PROJECT_PREFIX}-app" --from-literal WEBHOOK_SECRET="${WEBHOOK_SECRET}" --from-literal IBMCLOUD_API_KEY="${IBMCLOUD_API_KEY}" --from-literal ICR_NAMESPACE="${ICR_NAMESPACE}" --from-literal ICR_IMAGE="${ICR_IMAGE}"
We also set the gh
cli to use the newly cloned repo as the default. This ensures our variables and secrets are attached to the correct repoistory
gh repo create --clone "${PROJECT_PREFIX}-ce-app" --public --template cloud-design-dev/simple-flask-ce-app && cd "${PROJECT_PREFIX}-ce-app"
gh repo set-default
gh workflow enable build-push-icr.yaml
gh variable set REGISTRY_NAMESPACE --body "${ICR_NAMESPACE}"
gh variable set REGISTRY_IMAGE --body "${ICR_IMAGE}"
gh variable set REGISTRY_ENDPOINT --body "${ICR_ENDPOINT}"
gh secret set REGISTRY_PASSWORD --body "${IBMCLOUD_API_KEY}"
gh workflow run build-push-icr.yaml --ref main
JOB_ID=$(gh run list --workflow=build-push-icr.yaml -L 1 --json databaseId --jq '.[].databaseId')
gh run view "${JOB_ID}"
If the Github action completes we can move on to creating our Code Engine application and our Webhook reciever function. First up lets create our web application, it will take a few moments to deploy and configure the frontend ingress for our application:
ibmcloud ce app create --name "${PROJECT_PREFIX}-app" --registry-secret "${PROJECT_PREFIX}-icr-secret" --image "private.${ICR_ENDPOINT}/${ICR_NAMESPACE}/${ICR_IMAGE}:latest" --port "8080"
After a few minutes you should see output similar to this:
ibmcloud ce app create --name "${PROJECT_PREFIX}-app" --registry-secret "${PROJECT_PREFIX}-icr-secret" --image "private.${ICR_ENDPOINT}/${ICR_NAMESPACE}/${ICR_IMAGE}:latest" --port "8080"
Creating application 'btbx-app'...
The Route is still working to reflect the latest desired specification.
Configuration 'btbx-app' is waiting for a Revision to become ready.
Ingress has not yet been reconciled.
Waiting for load balancer to be ready.
Run 'ibmcloud ce application get -n btbx-app' to check the application status.
OK
https://btbx-app.1hijp0rx5e1d.us-east.codeengine.appdomain.cloud
Now we can move on to deploying our webhook function in Code Engine:
ibmcloud ce function create --name "${PROJECT_PREFIX}-fn" --env-from-secret "${PROJECT_PREFIX}-function-secret" --runtime python-3.11 --build-source https://github.com/cloud-design-dev/gh-webhook-function.git
Code Engine will pull out source code and build a container for our function and expose a Public endpoint. By default Code Engine will use its own pregenerated namespace to store the code bundle that is built for the function.
ibmcloud ce function create --name "${PROJECT_PREFIX}-fn" --env-from-secret "${PROJECT_PREFIX}-function-secret" --runtime python-3.11 --build-source https://github.com/cloud-design-dev/gh-webhook-function.git
Preparing function 'btbx-fn' for build push...
Creating function 'btbx-fn'...
Submitting build run 'btbx-fn-run-240528-105521517'...
Creating image 'private.de.icr.io/ce--6c272-1hijp0rx5e1d/function-btbx-fn:240528-1555-o9q6y'...
Waiting for build run to complete...
Build run status: 'pending'
Build run status: 'running'
Build run completed successfully.
Run 'ibmcloud ce buildrun get -n btbx-fn-run-240528-105521517' to check the build run status.
Waiting for function 'btbx-fn' to become ready...
Function 'btbx-fn' is ready.
OK
Run 'ibmcloud ce function get -n btbx-fn' to see more details.
https://btbx-fn.1hijp0rx5e1d.us-east.codeengine.appdomain.cloud
The last step is to add our newly created webhook to the Github repository
WEBHOOK_URL=$(ibmcloud ce fn get --name "${PROJECT_PREFIX}-fn" --output json | jq -r '.endpoint')
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "/repos/${GITHUB_USERNAME}/${PROJECT_PREFIX}-ce-app/hooks" -f "name=web" -F "active=true" -f "events[]=workflow_run" -f "config[url]=${WEBHOOK_URL}" -f "config[content_type]=json" -f "config[insecure_ssl]=0" -f "config[secret]=${WEBHOOK_SECRET}"
In our cloned directory we can run the folling to kick off the Github Action > Webhook > Code Engine flow:
echo -e "\nThis is a test at $(date)" | tee -a README.md
git add .
git commit -m "Testing app update process"
git push