Rules Overview
Understanding the rules system architecture and execution flow.
What are Rules?
Rules are the core automation units in asana-github-sync. Each rule defines:
- When to trigger (conditions that must match)
- Then what to do (actions to perform)
rules:
- when:
event: pull_request
action: opened
then:
update_fields:
'1234567890': '0987654321'Rule Structure
Basic Anatomy
rules:
- when: # Conditions block
event: ... # Required: GitHub event name
action: ... # Optional: Event action filter
# ... more conditions
then: # Actions block
update_fields: ... # Or create_task, mark_complete, post_pr_commentMultiple Rules
Rules are evaluated independently. All matching rules execute:
rules:
- when:
event: pull_request
action: opened
then:
update_fields:
'1111111111': '2222222222'
- when:
event: pull_request
action: labeled
label: ready-for-qa
then:
update_fields:
'3333333333': '4444444444'Execution Flow
GitHub Event
↓
Action receives webhook
↓
Extract PR and task URLs
↓
For each rule:
├─→ Check conditions (AND logic)
│ ├─→ event matches? ✓
│ ├─→ action matches? ✓
│ ├─→ draft matches? ✓
│ └─→ All match? Continue
│
└─→ Execute actions
├─→ Evaluate templates
├─→ Call Asana API
└─→ Post PR comment (if configured)Condition Logic
AND Logic
All conditions in a when block must match:
when:
event: pull_request # Must match
action: opened # AND must match
draft: true # AND must match
label: urgent # AND must matchIf any condition fails, the rule is skipped.
OR Logic
Create separate rules for OR behavior:
# Rule 1: Match opened
- when:
event: pull_request
action: opened
then:
# ...
# Rule 2: Match reopened
- when:
event: pull_request
action: reopened
then:
# Same actionOr use array syntax for single condition:
when:
event: pull_request
action: [opened, reopened] # Matches eitherDefault Behaviors
Draft PR Matching
By default (when draft is omitted), rules match both draft and non-draft PRs:
# This matches ALL PRs (draft and non-draft):
when:
event: pull_request
action: opened
# draft is not specified, so it matches bothTo match only non-draft PRs:
when:
event: pull_request
action: opened
draft: false # Only match ready-for-review PRsTo match only draft PRs:
when:
event: pull_request
action: opened
draft: true # Only match draft PRsBest Practice
Most teams should explicitly specify draft: false to avoid triggering rules on draft PRs:
when:
event: pull_request
action: opened
draft: false # Skip draftsHas Asana Tasks
The has_asana_tasks condition determines create vs update:
# Create task (requires has_asana_tasks: false)
- when:
event: pull_request
has_asana_tasks: false
then:
create_task:
project: '1234567890'
# ...
# Update existing tasks (default: has_asana_tasks: true)
- when:
event: pull_request
# Omitting has_asana_tasks means true
then:
update_fields:
'1234567890': '0987654321'Action Types
Update Actions
Modify existing Asana tasks (requires has_asana_tasks: true):
update_fields- Update custom fieldsmark_complete- Mark task completepost_pr_comment- Add GitHub PR comment
Create Actions
Create new Asana tasks (requires has_asana_tasks: false):
create_task- Create task with fields and metadata
Combining Actions
You can combine multiple actions in a single rule:
then:
update_fields:
'1234567890': '0987654321'
mark_complete: true
post_pr_comment: "Task updated and completed!"Restrictions:
- Cannot use
create_taskwithupdate_fieldsormark_complete - Must have at least one action in every
thenblock
Template Evaluation
Actions support Handlebars templates with PR context:
then:
update_fields:
'1234567890': 'PR #{{pr.number}}: {{pr.title}}'
'0987654321': '{{pr.author}}'
post_pr_comment: |
Updated task for {{pr.title}}
Author: {{pr.author}}Available Context
pr.*- PR data (number, title, body, author, etc.)event.*- Event data (name, action)label.*- Label data (when applicable)- Handlebars helpers - Text processing, extraction, user mapping
See Templates for complete guide.
Rule Precedence
Multiple Rules Can Match
All matching rules execute independently. If a PR matches multiple rules, all of them run:
rules:
# Rule 1: All PRs
- when:
event: pull_request
action: opened
then:
update_fields:
'1111111111': '2222222222'
# Rule 2: Bot PRs (also matches!)
- when:
event: pull_request
action: opened
author: dependabot[bot]
then:
update_fields:
'3333333333': '4444444444'For a dependabot PR, both rules execute because both conditions match.
Last Rule Wins for Conflicts
When multiple rules update the same field GID, the last matching rule's value is used:
rules:
# Rule 1: Sets field to "In Review"
- when:
event: pull_request
action: opened
then:
update_fields:
'1234567890': 'In Review'
# Rule 2: Sets same field to "Bot PR" (this wins!)
- when:
event: pull_request
action: opened
author: dependabot[bot]
then:
update_fields:
'1234567890': 'Bot PR'For a dependabot PR, field 1234567890 will be set to 'Bot PR' because Rule 2 comes last.
Order Matters
Rules are evaluated in the order they appear in your configuration. Put more specific rules after general rules to override field values.
Different Fields Don't Conflict
Rules updating different fields all apply:
rules:
- when:
event: pull_request
action: opened
then:
update_fields:
'1111111111': 'In Review' # Status field
'2222222222': '{{pr.author}}' # Author field
- when:
event: pull_request
action: opened
author: dependabot[bot]
then:
update_fields:
'3333333333': 'Bot' # Type field (no conflict)All three fields are updated for dependabot PRs.
Using Precedence Strategically
Pattern: General + Specific
rules:
# General rule for all PRs
- when:
event: pull_request
action: opened
then:
update_fields:
'1111111111': 'In Review'
'2222222222': 'Normal'
# Override for urgent PRs
- when:
event: pull_request
action: opened
label: urgent
then:
update_fields:
'2222222222': 'Urgent' # Overrides 'Normal'
# '1111111111' stays 'In Review' from first ruleFor urgent PRs: field 1111111111 = 'In Review', field 2222222222 = 'Urgent'
Validation
Rules are validated before execution:
- Required fields:
eventin conditions, at least one action - Mutual exclusivity:
create_taskvs update actions - GID format: Must be numeric strings (e.g.,
'1234567890') - Condition values: Correct types (boolean for
draft, string forevent)
Invalid rules fail with descriptive error messages.
Real-World Patterns
Progressive Enhancement
Start simple, add complexity:
rules:
# Step 1: Basic status update
- when:
event: pull_request
action: opened
then:
update_fields:
'1234567890': '1111111111' # "In Review"
# Step 2: Add completion on merge
- when:
event: pull_request
action: closed
merged: true
then:
update_fields:
'1234567890': '2222222222' # "Shipped"
mark_complete: trueLifecycle Tracking
Track entire PR journey:
rules:
- when: { event: pull_request, action: opened }
then: { update_fields: { '1111': '2222' } } # "In Review"
- when: { event: pull_request, action: ready_for_review }
then: { update_fields: { '1111': '2222' } } # "In Review"
- when: { event: pull_request, action: labeled, label: approved }
then: { update_fields: { '1111': '3333' } } # "Approved"
- when: { event: pull_request, action: closed, merged: true }
then:
update_fields: { '1111': '4444' } # "Shipped"
mark_complete: trueBot vs Human Handling
Different behavior for bots:
rules:
# Create tasks for bots
- when:
event: pull_request
action: opened
has_asana_tasks: false
author: [dependabot[bot]]
then:
create_task:
project: '1234567890'
title: '{{clean_title pr.title}}'
# Update tasks for humans
- when:
event: pull_request
action: opened
has_asana_tasks: true
then:
update_fields:
'1234567890': '0987654321'Next Steps
- Conditions - All available conditions
- Actions - All available actions
- Templates - Handlebars templating guide
- Examples - Real-world workflows