From 759834680392b59be61e1bf787864c88c067794a Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 8 Mar 2026 22:00:27 +0800 Subject: [PATCH] perf: hoist regexp.MustCompile to package-level vars Fixes #20026 Problem: - validateExpressionForDangerousProps called regexp.MustCompile twice - One call was inside a for loop (per-iteration allocation) - This is called for every expression in every compiled workflow - Regex allocations accumulated significantly in hot path Solution: - Added exprPartSplitRe and exprNumericPartRe as package-level vars - These are compiled once at init time, not per-call/iteration - Replaced inline MustCompile calls with references to these vars Impact: - Eliminates repeated regex compilation in expression validation - Reduces allocations in hot path - No behavior change, pure performance optimization --- pkg/workflow/expression_validation.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/workflow/expression_validation.go b/pkg/workflow/expression_validation.go index 590ca8379ad..a64d202f301 100644 --- a/pkg/workflow/expression_validation.go +++ b/pkg/workflow/expression_validation.go @@ -77,6 +77,13 @@ var ( stringLiteralRegex = regexp.MustCompile(`^'[^']*'$|^"[^"]*"$|^` + "`[^`]*`$") // numberLiteralRegex matches integer and decimal number literals (with optional leading minus) numberLiteralRegex = regexp.MustCompile(`^-?\d+(\.\d+)?$`) + + // exprPartSplitRe splits expressions on dots and brackets (e.g., "github.event.issue" -> ["github", "event", "issue"]) + // Used in validateExpressionForDangerousProps to parse property access patterns + exprPartSplitRe = regexp.MustCompile(`[.\[\]]+`) + // exprNumericPartRe matches numeric indices (e.g., "0" in "assets[0]") + // Used to filter out array indices when checking for dangerous property names + exprNumericPartRe = regexp.MustCompile(`^\d+$`) ) // validateExpressionSafety checks that all GitHub Actions expressions in the markdown content @@ -209,11 +216,11 @@ func validateExpressionForDangerousProps(expression string) error { // Split expression into parts handling both dot notation (e.g., "github.event.issue") // and bracket notation (e.g., "release.assets[0].id") // Filter out numeric indices (e.g., "0" in "assets[0]") - parts := regexp.MustCompile(`[.\[\]]+`).Split(trimmed, -1) + parts := exprPartSplitRe.Split(trimmed, -1) for _, part := range parts { // Skip empty parts and numeric indices - if part == "" || regexp.MustCompile(`^\d+$`).MatchString(part) { + if part == "" || exprNumericPartRe.MatchString(part) { continue }