Skip to content

Commit e72a377

Browse files
authored
improve(workshop): step 15 readability, callout density, and active-learning density (#1785)
1 parent 65021db commit e72a377

2 files changed

Lines changed: 71 additions & 23 deletions

File tree

workshop/15-conditional-logic.md

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
## 🎯 What You'll Do
88

9-
Add a conditional check to your daily-status workflow so it only posts a summary when there have been recent commits. You'll learn how to use shell commands to gather context and pass that context into your AI prompt.
9+
Add a conditional check to your daily-status workflow so it only posts a summary when there have been recent commits. You'll learn how to use shell commands to gather context, expose that context as step outputs, and wire it into an `if:` condition that short-circuits the agent job entirely on quiet days.
1010

1111
## 📋 Before You Start
1212

@@ -17,16 +17,16 @@ Add a conditional check to your daily-status workflow so it only posts a summary
1717

1818
### Understand the problem
1919

20-
Right now your daily-status workflow runs every weekday — even on days when nothing happened. That means noisy, unhelpful summaries like "No activity to report." Conditional logic lets you skip the AI call entirely on quiet days.
20+
Your daily-status workflow currently runs every weekday regardless of repository activity, which means it can produce empty or near-empty summaries like "No activity to report" on quiet days. Over time these hollow reports erode confidence in the tool because readers learn to ignore them. Conditional logic solves this by inspecting repository state in a deterministic shell step before any AI processing begins, then skipping the agent job entirely when the precondition is not met.
2121

22-
The approach:
23-
1. Run a shell command to count recent commits.
24-
2. Store the result in an output variable.
25-
3. Add a top-level `if:` in workflow [frontmatter](https://github.github.com/gh-aw/reference/frontmatter/) to skip the agent job when the count is zero.
22+
The approach breaks into three parts:
23+
1. Run a shell command to count commits from the last 24 hours and write the result to `$GITHUB_OUTPUT`.
24+
2. Reference that output using the `steps` context expression `${{ steps.recent.outputs.commit_count }}`.
25+
3. Add a top-level `if:` key in the workflow [frontmatter](https://github.github.com/gh-aw/reference/frontmatter/) that skips the agent job when the count evaluates to zero.
2626

2727
### Add a commit-count step
2828

29-
Open your daily-status workflow file (e.g., `.github/workflows/daily-status.md`) and add this inside the YAML frontmatter under `steps:`:
29+
Open your daily-status workflow file (e.g., `.github/workflows/daily-status.md`) and add the following block inside the YAML frontmatter under `steps:`:
3030

3131
```yaml
3232
steps:
@@ -37,38 +37,49 @@ steps:
3737
echo "commit_count=$COUNT" >> $GITHUB_OUTPUT
3838
```
3939
40-
This shell command:
41-
- Uses `git log` with a time filter to list commits from the last 24 hours.
42-
- Counts the lines with `wc -l`.
43-
- Writes the result to `$GITHUB_OUTPUT` so the next step can read it.
40+
This shell command uses `git log` with a `--since` time filter to list only commits from the last 24 hours, pipes the output through `wc -l` to count the lines, strips surrounding whitespace with `tr -d ' '`, and writes the final integer to `$GITHUB_OUTPUT` — a special GitHub Actions file that shares values between steps using `key=value` notation. The `id: recent` field is essential: it creates a named slot in the `steps` context so the value can be referenced as `steps.recent.outputs.commit_count` in later steps or in the top-level `if:` condition.
4441

4542
> [!NOTE]
4643
> <details>
47-
> <summary>`$GITHUB_OUTPUT` is a special GitHub Actions file. Anything you write in the format `key=value` becomes available to later steps as `steps.<id>.outputs.key`.</summary>
44+
> <summary>`$GITHUB_OUTPUT` makes step outputs available to later steps as `steps.<id>.outputs.key`.</summary>
4845
>
49-
> Want to understand how `${{ steps.recent.outputs.commit_count }}` works and what other context objects exist? See [Side Quest: GitHub Actions Expressions and Contexts](side-quest-15-01-expressions-and-contexts.md).
46+
> For a deeper explanation of how the `steps` context works alongside other context objects (`github`, `env`, `runner`), how to use built-in expression functions like `contains()` and `toJSON()`, and how to chain conditions with `&&` and `||`, see [Side Quest: GitHub Actions Expressions and Contexts](side-quest-15-01-expressions-and-contexts.md).
5047
>
5148
> </details>
5249

5350
### Add a top-level condition in frontmatter
5451

55-
In the same frontmatter block, add a top-level `if:` key (at the same level as `on:` and `steps:`):
52+
In the same frontmatter block, add a top-level `if:` key at the same indentation level as `on:` and `steps:`:
5653

5754
```yaml
5855
if: steps.recent.outputs.commit_count != '0'
5956
```
6057

61-
This condition skips the compiler-generated agent job entirely when `commit_count` is `0`.
58+
This condition is embedded into the generated lock file during [compilation](https://github.github.com/gh-aw/reference/compilation-process/); at runtime, GitHub Actions evaluates it and skips the agent job entirely whenever `commit_count` evaluates to `'0'`. You can also reference the count inside your prompt text to give the model concrete context — for example: `"Summarise the last ${{ steps.recent.outputs.commit_count }} commits"` anchors the analysis to the actual number of changes rather than leaving the model to guess the scope.
6259

63-
> [!TIP]
64-
> You can use `${{ steps.recent.outputs.commit_count }}` inside your prompt text too — for example: "Summarise the last ${{ steps.recent.outputs.commit_count }} commits."
60+
### Exercise: Add a weekend skip condition
6561

66-
### Test it locally first
62+
Now that the commit-count condition is in place, extend the workflow to also skip execution on weekends. This exercise reinforces how to chain multiple conditions in a single `if:` expression.
6763

68-
Use `workflow_dispatch` to trigger the workflow manually. Check the run log:
64+
1. Add a step that writes the current day name as an output:
6965

70-
- If there were recent commits, the summary should run.
71-
- If not, you should see the agent job marked as **skipped** (a grey icon in the Actions UI).
66+
```yaml
67+
- name: Check day of week
68+
id: day
69+
run: echo "day=$(date +%A)" >> $GITHUB_OUTPUT
70+
```
71+
72+
1. Update the top-level `if:` to combine both conditions using `&&`:
73+
74+
```yaml
75+
if: steps.recent.outputs.commit_count != '0' && steps.day.outputs.day != 'Saturday' && steps.day.outputs.day != 'Sunday'
76+
```
77+
78+
1. Compile the workflow with `gh aw compile` to regenerate the lock file with the combined condition.
79+
80+
1. Trigger a manual `workflow_dispatch` run from the Actions tab.
81+
82+
1. Inspect the run log: on a weekday with commits the agent job should complete normally; on a weekend or a day with no commits it should appear as **skipped** with a grey icon, as shown below.
7283

7384
![Skipped step in GitHub Actions](images/15-skipped-step.svg)
7485

@@ -80,10 +91,10 @@ After editing the frontmatter, compile the workflow to confirm everything is val
8091
gh aw compile
8192
```
8293

83-
You should see `✅ Compiled successfully`. This regenerates your `.lock.yml` file with the updated conditional logic.
94+
You should see `✅ Compiled successfully`. This regenerates your `.lock.yml` file with the updated conditional logic embedded in the job definition.
8495

8596
> [!NOTE]
86-
> The `if:` condition is applied during [compilation](https://github.github.com/gh-aw/reference/compilation-process/) — it won't take effect until you compile and push both files.
97+
> The `if:` condition is applied during [compilation](https://github.github.com/gh-aw/reference/compilation-process/) and will not take effect until you compile and push both the `.md` source and the updated `.lock.yml` file.
8798

8899
### Commit and push your conditional logic
89100

workshop/side-quest-15-01-expressions-and-contexts.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,49 @@ if: contains(github.event.head_commit.message, '[skip ci]')
119119
> [!NOTE]
120120
> Expressions are evaluated on the GitHub Actions runner, not inside the AI agent. Use them for workflow control flow, not for shaping the AI prompt at runtime — pass values to the prompt via environment variables in your brief instead.
121121

122+
### Combine multiple conditions
123+
124+
The `&&` (AND) and `||` (OR) operators let you build composite conditions that express more nuanced rules than a single comparison allows. When combining multiple shell-derived outputs, keep in mind that all values written to `$GITHUB_OUTPUT` arrive as strings, so always compare them against quoted literals.
125+
126+
```yaml
127+
# Run only when there are commits AND the branch is main
128+
if: steps.recent.outputs.commit_count != '0' && github.ref == 'refs/heads/main'
129+
130+
# Run when triggered manually OR there are recent commits
131+
if: github.event_name == 'workflow_dispatch' || steps.recent.outputs.commit_count != '0'
132+
133+
# Skip weekends by combining day-of-week outputs from a shell step
134+
if: steps.day.outputs.day != 'Saturday' && steps.day.outputs.day != 'Sunday'
135+
```
136+
137+
### Gather time-based context with shell steps
138+
139+
Some conditions require information that is not available in any context object — for example, the current day of the week or the number of commits since a given timestamp. You can capture this data in a dedicated shell step and then reference it like any other output.
140+
141+
A step that exposes the current day name:
142+
143+
```yaml
144+
- name: Check day of week
145+
id: day
146+
run: echo "day=$(date +%A)" >> $GITHUB_OUTPUT
147+
```
148+
149+
Once this step runs, `steps.day.outputs.day` holds a value like `Monday` or `Saturday`. Combine it with a commit-count check to build a condition that skips the agent job on both quiet days and weekends:
150+
151+
```yaml
152+
if: steps.recent.outputs.commit_count != '0' && steps.day.outputs.day != 'Saturday' && steps.day.outputs.day != 'Sunday'
153+
```
154+
155+
This pattern — deterministic shell step produces a string output, `if:` expression reads that output — applies broadly wherever you need workflow control flow based on data that is not already in a GitHub Actions context object.
156+
122157
## ✅ Checkpoint
123158

124159
- [ ] You can explain what `${{ }}` does and when GitHub evaluates it
125160
- [ ] You can name at least three context objects and what they contain
126161
- [ ] You understand how `id:` connects a step's output to the `steps` context
127162
- [ ] You can write an `if:` condition that skips a step based on a previous output
163+
- [ ] You can combine two or more conditions using `&&` and `||`
164+
- [ ] You can write a shell step that captures time-based data (day of week, date) as a step output
128165

129166
<!-- journey: all -->
130167
**Next:** [Connect a Live Data Source to Your Workflow](16-connect-data-source.md)

0 commit comments

Comments
 (0)