Skip to content

perf(parser): fix ParseWorkflow regression — eliminate redundant file read and YAML parse#22472

Merged
pelikhan merged 4 commits intomainfrom
copilot/fix-parse-workflow-performance-regression
Mar 23, 2026
Merged

perf(parser): fix ParseWorkflow regression — eliminate redundant file read and YAML parse#22472
pelikhan merged 4 commits intomainfrom
copilot/fix-parse-workflow-performance-regression

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 23, 2026

BenchmarkParseWorkflow regressed ~12% (3.1ms → 3.5ms) due to redundant I/O and serialization work in the ParseWorkflowFile hot path.

Root causes

  • Double file read + YAML parse: processToolsAndMarkdown called ExtractWorkflowNameFromMarkdown(cleanPath) which re-read the file from disk and re-ran ExtractFrontmatterFromContent (YAML unmarshal, strings.Split/Join) — even though result.Markdown was already available from parseFrontmatterSection.

  • Unnecessary YAML serialization: hasContentContext marshaled the parsed on: map back to a YAML string just to run strings.Contains checks against event names.

  • Unnecessary map copy: filterIgnoredFields always allocated a copy of the frontmatter map even when no ignored fields were present (the common case).

Changes

  • pkg/parser/frontmatter_content.go: Add ExtractWorkflowNameFromMarkdownBody(markdownBody, virtualPath) — scans an already-extracted markdown body for the H1 header, skipping the file read and YAML parse entirely.

  • pkg/workflow/compiler_orchestrator_tools.go: Use result.Markdown (already parsed) instead of ExtractWorkflowNameFromMarkdown. Replace yaml.Marshal + strings.Contains in hasContentContext with direct map[string]bool key lookup; remove the now-unused goccy/go-yaml import.

  • pkg/parser/schema_utilities.go: In filterIgnoredFields, short-circuit and return the original map unchanged when none of the ignored fields are present.

Result

BenchmarkParseWorkflow  ~3,472,142 ns/op  →  ~1,252,809 ns/op  (-64%)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw 64/pkg/tool/linurev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel 64/pkg/tool/linurev-parse /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel 39218b93 /usr/bin/git git (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name --noprofile git /usr/bin/git --show-toplevel git 0/x64/bin/node git rev-�� '**/*.ts' '**/*.json' --ignore-path ../../../.prettierignore git n-dir/node --show-toplevel git 0/x64/bin/node git (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha -bool -buildtags 7388894/b310/vet.cfg -errorsas -ifaceassert -nilfunc /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -uns�� -unreachable=false /tmp/go-build2587388894/b179/vet.cfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha --show-toplevel /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git -bool -buildtags /opt/hostedtoolc--show-toplevel git rev-�� --show-toplevel /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git -bool -buildtags /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha --show-toplevel git er: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabl--show-toplevel --show-toplevel git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -bool -buildtags /usr/bin/git -errorsas -ifaceassert -nilfunc git rev-�� --show-toplevel -tests /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha FETCH_HEAD^{commit} (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha k/gh-aw/gh-aw/pkg/testutil/tempdir.go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha FETCH_HEAD^{commit} (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha pkg/mod/github.com/stretchr/testify@v1.11.1/assert/assertion_com-errorsas pkg/mod/github.com/stretchr/testify@v1.11.1/assert/assertion_for-ifaceassert /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha FETCH_HEAD^{commit} (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� nt/action/git/ref/tags/v999.999.999 git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha FETCH_HEAD^{commit} (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� -aw/git/ref/tags/v1.0.0 git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha --show-toplevel ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git --noprofile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/sed --show-toplevel git /usr/bin/git sed (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha --show-toplevel ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git --noprofile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/ls --show-toplevel git /usr/bin/git ls (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha --show-toplevel ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git --noprofile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 node /opt/hostedtoolcache/node/24.14.0/x64/bin/node /usr/bin/basenamgit git x_amd64/link node /opt�� run format:cjs /opt/hostedtoolcache/node/24.14.0/x64/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/n--show-toplevel /usr/bin/git git x86_64/bash sh (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 build_command.go /opt/hostedtoolcache/go/1.25.0/x-nilfunc /usr/bin/sed git de/node/bin/bashgithub.token /opt/hostedtoolcache/go/1.25.0/x-importcfg stlo�� -w pkg/workflow/create_pull_request-w x_amd64/link pkg/workflow/dangit pkg/workflow/danrev-parse pkg/workflow/dep--show-toplevel x_amd64/link (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 .go x_amd64/compile /usr/bin/sed git /opt/hostedtoolc--get x_amd64/compile -c echo "��� Go code formatted" node x_amd64/compile /usr/bin/git git k/_temp/ghcca-no--show-toplevel x_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 node /home/REDACTED/go/bin/node /usr/bin/grep git ache/go/1.25.0/x64/bin/bash node /opt�� run format:cjs /home/node_modules/.bin/sh /usr/bin/git git tnet/tools/bash sh (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 node /opt/hostedtoolcache/go/1.25.0/x64/bin/node /usr/bin/sed git x_amd64/vet node stlo�� run format:cjs x_amd64/link /usr/bin/git git n-dir/bash x_amd64/link (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 rkflow/js/**/*.json x_amd64/compile erignore git x_amd64/link x_amd64/compile -c npx prettier --write '**/*.cjs' remote.origin.url x_amd64/link /home/REDACTED/work/_temp/uv-python-dir/sh /usr/bin/git git /opt/hostedtoolc--show-toplevel sh (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 on rkflow/js/**/*.json /../../.prettiergit erignore x_amd64/vet sh -c npx prettier --write '**/*.cjs' '**/*.ts' '**/*.json' --ignore-path ../../../.pr**/*.json x_amd64/vet /opt/hostedtoolcache/uv/0.10.12/x86_64/sh /usr/bin/git git /opt/hostedtoolc--get sh (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path -m owner /usr/bin/git 0 -j ACCEPT git 0/x6�� --show-toplevel git n-dir/node --show-toplevel git 0/x64/bin/node git (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 git 0/x64/bin/node git tion�� --show-toplevel git son ignore git ndor/bin/bash git (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 git x_amd64/link bash --no�� --noprofile x_amd64/link /home/REDACTED/work/gh-aw/gh-aw/no-nolocalimports /usr/bin/git git sh node (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel ache/go/1.25.0/xrev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel /opt/hostedtoolcrev-parse /usr/bin/git git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha --show-toplevel git 64/bin/node --show-toplevel git 0/x64/bin/node git tion�� ithub-script/git-errorsas node son ignore git ache/node/24.14./tmp/go-build620333307/b443/_pkg_.a git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel git 0/x64/bin/node git rev-�� --show-toplevel node ache/node/24.14.-lang=go1.25 ignore git ache/node/24.14./tmp/go-build620333307/b441/_pkg_.a git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha .." git 0/x64/bin/bash --show-toplevel git 0/x64/bin/node git rev-�� --show-toplevel node e_modules/.bin/n-nilfunc /usr/bin/git git ache/node/24.14./tmp/go-build620333307/b445/_pkg_.a git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha --show-toplevel git k/_temp/ghcca-node/node/bin/bash --show-toplevel git 0/x64/bin/node git rev-�� --show-toplevel node ache/node/24.14.0/x64/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/node/home/REDACTED/work/gh-aw/gh-aw/.github/workflows /usr/bin/git git 0/x64/bin/bash git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha --show-toplevel git x86_64/bash --show-toplevel git 0/x64/bin/node git rev-�� --show-toplevel node k/gh-aw/gh-aw/ac-buildmode=exe /usr/bin/git git ache/node/24.14.-bool git (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha tags/v6 x_amd64/vet /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha --show-toplevel git /usr/bin/git --show-toplevel ache/go/1.25.0/xrev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel /opt/hostedtoolcrev-parse /usr/bin/git git (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion /../../.prettiergit erignore x_amd64/compile sh -c 36/001/test-empty-frontmatter.md x_amd64/compile /home/node_modules/.bin/node /usr/bin/git git k/_temp/uv-pytho--show-toplevel node (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo /usr/bin/git .json..." git 0/x64/bin/node mSh_p7cdqAoJ 0/x6�� --show-toplevel git 0/x64/bin/node --show-toplevel git 0/x64/bin/node git (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo tions/node_modules/.bin/sh --show-toplevel git 0/x64/bin/node git rev-�� */*.ts' '**/*.json' --ignore-path ../../../.prettierignore git bin/sh --show-toplevel git (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: /tmp/go-build620333307/b400/cli.test /tmp/go-build620333307/b400/cli.test -test.testlogfile=/tmp/go-build620333307/b400/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true --show-toplevel git 0/x64/bin/node git rev-�� --show-toplevel gh 64/bin/node /repos/actions/ggit --jq (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name --noprofile git /usr/bin/git --show-toplevel git 0/x64/bin/node git rev-�� '**/*.ts' '**/*.json' --ignore-path ../../../.pr**/*.json git ode --show-toplevel git 0/x64/bin/node git (http block)

If you need me to access, download, or install something from one of these locations, you can either:


⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.

…ile read and YAML parse

Resolves the 12% BenchmarkParseWorkflow regression by removing three
sources of unnecessary work in the ParseWorkflowFile hot path:

1. ExtractWorkflowNameFromMarkdown was re-reading the workflow file
   from disk and re-parsing its YAML frontmatter even though the
   parsed result (result.Markdown) was already available.
   Added ExtractWorkflowNameFromMarkdownBody() to scan the
   already-extracted markdown body directly.

2. hasContentContext marshaled the parsed 'on' map to a YAML string
   just to run strings.Contains checks. Replaced with direct map key
   lookup — no allocation, same semantics.

3. filterIgnoredFields always copied the frontmatter map even when no
   ignored fields were present (the common case). Now returns the
   original map unchanged when no filtering is needed.

Benchmark: ~3,472,142 ns/op → ~1,252,809 ns/op (~64% faster)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/94b84a31-b038-466b-bdeb-b8cf9c6ecb27
Copilot AI changed the title [WIP] Fix performance regression in ParseWorkflow by reducing execution time perf(parser): fix ParseWorkflow regression — eliminate redundant file read and YAML parse Mar 23, 2026
Copilot AI requested a review from pelikhan March 23, 2026 17:46
@pelikhan pelikhan marked this pull request as ready for review March 23, 2026 17:46
Copilot AI review requested due to automatic review settings March 23, 2026 17:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Optimizes the ParseWorkflowFile/compile hot path by eliminating redundant disk reads, YAML (re)parsing/serialization, and unnecessary map allocations introduced by a regression.

Changes:

  • Reuse already-parsed markdown body to extract workflow name without re-reading/parsing the file.
  • Replace YAML marshal + substring scanning of on: with direct trigger key inspection.
  • Avoid copying frontmatter maps when no ignored fields are present.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
pkg/workflow/compiler_orchestrator_tools.go Uses in-memory markdown for name extraction; simplifies hasContentContext to key lookups.
pkg/parser/frontmatter_content.go Adds ExtractWorkflowNameFromMarkdownBody to extract H1 title from an already-parsed markdown body.
pkg/parser/schema_utilities.go Short-circuits filterIgnoredFields to avoid allocations when nothing is filtered.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +187 to +199
scanner := bufio.NewScanner(strings.NewReader(markdownBody))
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "# ") {
workflowName := strings.TrimSpace(line[2:])
log.Printf("Found workflow name from H1 header: %s", workflowName)
return workflowName, nil
}
}

defaultName := generateDefaultWorkflowName(virtualPath)
log.Printf("No H1 header found, using default name: %s", defaultName)
return defaultName, nil
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExtractWorkflowNameFromMarkdownBody uses bufio.Scanner but never checks scanner.Err(). If the markdown contains a very long line (over Scanner's token limit), Scan() will stop early and this function will silently fall back to the default name instead of returning an error. Consider setting a larger scanner buffer (or using a different reader) and returning scanner.Err() when non-nil so failures are not hidden.

Copilot uses AI. Check for mistakes.
Comment on lines +179 to +200
// ExtractWorkflowNameFromMarkdownBody extracts the workflow name from an already-extracted
// markdown body (i.e. the content after the frontmatter has been stripped). This is more
// efficient than ExtractWorkflowNameFromMarkdown or ExtractWorkflowNameFromContent because it
// avoids the redundant file-read and YAML-parse that those functions perform when the caller
// already holds the parsed FrontmatterResult.
func ExtractWorkflowNameFromMarkdownBody(markdownBody string, virtualPath string) (string, error) {
log.Printf("Extracting workflow name from markdown body: virtualPath=%s, size=%d bytes", virtualPath, len(markdownBody))

scanner := bufio.NewScanner(strings.NewReader(markdownBody))
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "# ") {
workflowName := strings.TrimSpace(line[2:])
log.Printf("Found workflow name from H1 header: %s", workflowName)
return workflowName, nil
}
}

defaultName := generateDefaultWorkflowName(virtualPath)
log.Printf("No H1 header found, using default name: %s", defaultName)
return defaultName, nil
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are existing tests for ExtractWorkflowNameFromMarkdown, but the newly added ExtractWorkflowNameFromMarkdownBody is now used in the compiler hot path and currently has no direct test coverage. Please add unit tests covering at least: (1) markdown body with an H1, (2) no H1 -> default name based on virtualPath, and (3) H1 with extra spacing.

Copilot uses AI. Check for mistakes.
Comment on lines +356 to +366
contentEventKeys := map[string]bool{
"issues": true,
"pull_request": true,
"pull_request_target": true,
"issue_comment": true,
"pull_request_review_comment": true,
"pull_request_review": true,
"discussion": true,
"discussion_comment": true,
"slash_command": true,
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contentEventKeys is allocated as a new map on every hasContentContext call. Since this function sits in the workflow compile path (and this PR is performance-focused), consider making this a package-level var (or using a switch on eventName) to avoid per-call allocations.

Copilot uses AI. Check for mistakes.
@pelikhan pelikhan merged commit 6d15cdb into main Mar 23, 2026
175 of 176 checks passed
@pelikhan pelikhan deleted the copilot/fix-parse-workflow-performance-regression branch March 23, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[performance] Regression in ParseWorkflow: +12.0% slower

3 participants