How the GitHub Asana Request Review Action Parses Asana Task URLs from Pull Request Descriptions
The GitHub Asana Request Review Action extracts Asana task identifiers from pull request descriptions using the parseAsanaTaskLink function in asana.go, which applies two distinct regular expression patterns to support both modern workspace-based URLs and legacy project-based URLs.
This GitHub Action bridges GitHub pull requests with Asana by automatically scanning PR descriptions for valid Asana links. Written in Go, the implementation relies on specific regex matching logic defined in asana.go to identify supported URL formats and extract the necessary identifiers for API integration.
The parseAsanaTaskLink Function Implementation
The core URL parsing mechanism is implemented in the parseAsanaTaskLink function, defined at lines 18-30 of [asana.go](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go#L18-L30). This function attempts to match the PR description against two regular expression patterns sequentially, returning three strings: workspaceID, projectID, and taskID.
Modern v1 Workspace-Based Format
The action first attempts to match URLs following Asana's modern v1 format using the following pattern:
v1 := regexp.MustCompile(`https://app\.asana\.com/1/(\d+)/(?:task/|project/\d+/task/)(\d+)`)
This pattern captures two numeric groups:
- First
(\d+)→ workspaceID - Second
(\d+)→ taskID
When this pattern matches, the function returns the workspace ID and task ID, leaving projectID empty. This format supports both direct task links and URLs containing intermediate project path segments.
Legacy Project-Based Format
If the v1 pattern fails to match, the function falls back to the legacy "0" format:
var taskURLMatcher = regexp.MustCompile(`https://app.asana.com/0/(\d+)/(\d+)`)
This pattern captures:
- First
(\d+)→ projectID (note that workspace ID is not present in legacy URLs) - Second
(\d+)→ taskID
When this pattern matches, projectID is populated while workspaceID remains empty.
Integration with Pull Request Handling
The URL parser is invoked in [handler.go](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go#L53-L55) using the pull request body as input:
workspaceID, projectID, taskID := parseAsanaTaskLink(pr.PullRequest.GetBody())
If the returned taskID is empty—indicating neither regex pattern matched—the action logs "asana task url not found in description" and skips Asana integration for that pull request. This check prevents the action from attempting to create review subtasks when no valid Asana link is present.
Supported Asana URL Formats
The GitHub Asana Request Review Action recognizes three specific URL structures derived from the regex patterns:
- Legacy format:
https://app.asana.com/0/<project-id>/<task-id>— Captures legacy project and task identifiers. - Modern direct task:
https://app.asana.com/1/<workspace-id>/task/<task-id>— Captures workspace and task identifiers. - Modern project task:
https://app.asana.com/1/<workspace-id>/project/<project-id>/task/<task-id>— Captures workspace and task identifiers while ignoring the intermediate project path segment.
Query strings such as ?focus=true are automatically ignored by the regex patterns, allowing the action to correctly extract IDs regardless of additional URL parameters.
Practical Parsing Examples
The following examples demonstrate how parseAsanaTaskLink handles different URL formats:
// Example 1: Legacy format (project/task)
prBody := `Implemented feature X.
https://app.asana.com/0/364167036366785/1162650948650897
`
ws, proj, task := parseAsanaTaskLink(prBody)
// ws == "", proj == "364167036366785", task == "1162650948650897"
// Example 2: Modern workspace/task format with query parameter
prBody := `Please review.
https://app.asana.com/1/5590853215187/task/1209347772587937?focus=true
`
ws, proj, task = parseAsanaTaskLink(prBody)
// ws == "5590853215187", proj == "", task == "1209347772587937"
// Example 3: Modern workspace/project/task format
prBody := `Work in progress.
https://app.asana.com/1/5590853215187/project/364167036366785/task/1162650948650897
`
ws, proj, task = parseAsanaTaskLink(prBody)
// ws == "5590853215187", proj == "", task == "1162650948650897"
Summary
- The GitHub Asana Request Review Action uses the
parseAsanaTaskLinkfunction inasana.goto extract task identifiers from pull request descriptions. - Two regex patterns support both modern v1 workspace URLs (
https://app.asana.com/1/...) and legacy project URLs (https://app.asana.com/0/...). - The function returns
workspaceID,projectID, andtaskID, with only one of the first two populated depending on which URL format is detected. - If no valid URL is found during execution in
handler.go, the action logs a warning and skips Asana integration for that pull request. - Query parameters and focus modes appended to Asana URLs are ignored during parsing.
Frequently Asked Questions
What regex patterns does the GitHub Asana Request Review Action use to find Asana task URLs?
The action employs two patterns defined in asana.go: a modern v1 pattern `https://app\.asana\.com/1/(\d+)/(?:task/|project/\d+/task/)(\d+)` for workspace-based URLs, and a legacy pattern `https://app.asana.com/0/(\d+)/(\d+)` for project-based URLs. Both patterns are evaluated sequentially until a match is found.
Which Asana URL formats are supported by this GitHub Action?
The action supports three specific formats: legacy URLs structured as https://app.asana.com/0/123456789/987654321, modern direct task URLs formatted as https://app.asana.com/1/555/task/999, and modern project-task URLs like https://app.asana.com/1/555/project/123/task/999. Any URL not conforming to these patterns is ignored by the parser.
What happens if a pull request description contains no valid Asana task URL?
When parseAsanaTaskLink returns an empty taskID—indicating neither regex pattern matched—the handler in handler.go logs "asana task url not found in description" and bypasses all Asana integration steps for that pull request.
How does the action handle query parameters in Asana URLs?
The regex patterns match only up to the task ID portion of the URL, automatically ignoring query strings such as ?focus=true. This ensures the action correctly extracts numeric identifiers regardless of additional tracking parameters or view options appended to the link.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →