In the previous chapter, we introduced the Praktika Framework as the brain behind our CI system. We learned that it acts as a "Traffic Controller," deciding what work needs to be done.
But how does the controller know when to start working? And does it do the exact same work for a simple code check as it does for a major software release?
This brings us to CI Workflows.
Imagine you run a restaurant kitchen.
The Challenge: In software, a "Pull Request" (PR) is like the Lunch Rushโwe want fast feedback. A "Release" is like the State Dinnerโwe need deep, thorough testing. We cannot use the same checklist for both.
Central Use Case: We want to define two different plans:
To solve this, Praktika divides the work into Workflows.
A Trigger is the event that wakes up the CI.
master).This is a Python class that groups jobs together. It says: "If Trigger X happens, execute Job List Y."
In ClickHouse, we define workflows using Python code. We create a class that inherits from Workflow.
First, we define the workflow and give it a name.
from praktika import Workflow
class PullRequestWorkflow(Workflow):
# This name appears in GitHub checks
name = "PR Workflow"
# This configures WHEN this workflow runs
triggers = ["pull_request"]
Explanation: We created a blueprint called PullRequestWorkflow. It listens specifically for "pull_request" events.
A workflow is empty without jobs. We need to add the jobs (like building and testing) to it.
def configure(self):
# We create the jobs we need
build = BuildJob()
test = TestJob()
# We add them to this workflow
self.add_job(build)
self.add_job(test)
Explanation: Inside the configure method, we create job instances and register them. Now, when a PR is opened, these two jobs will be queued.
Just like we learned in Praktika Framework, we must define the order.
# Ensure 'test' runs AFTER 'build'
self.add_dependency(build, test)
Explanation: This ensures the workflow flows logically: Build first, then Test.
When an event happens (like a PR creation), the system has to pick the right workflow.
event_name: pull_request).triggers = ["pull_request"].configure() method.Here is how the selection process looks:
The actual code for these workflows is located in directories like ci/workflows/.
Praktika uses a Config object to manage the triggers more precisely. Instead of just a string, we might see code like this:
from praktika import Workflow, Config
class NightlyWorkflow(Workflow):
# Configure to run on a schedule (cron)
conf = Config(
trigger="schedule",
cron="0 2 * * *" # Run at 2:00 AM
)
Explanation: Here, the Config object gives us fine-grained control. We aren't just saying "Run on schedule," we are specifying exactly "2:00 AM".
Sometimes, even if the trigger matches, we might want to skip the workflow based on other criteria (like the branch name).
@classmethod
def is_enabled(cls, branch_name):
# Only run nightly tests on the master branch
if branch_name == "master":
return True
return False
Explanation: Before running configure(), Praktika checks is_enabled(). This acts as a final gatekeeper. If this returns False, the workflow aborts immediately, saving resources.
In this chapter, we learned that CI Workflows organize our tasks based on Triggers.
Now that we have a Workflow running, the very first thing it usually needs to do is compile the code.
In the next chapter, we will look at how we define the recipe for compiling ClickHouse in the Build Configuration.
Generated by Code IQ