Skip to content

XS⚠️ ◾ Structural Improvements#784

Open
muiriswoulfe wants to merge 3 commits intomainfrom
refactor/structural-improvements
Open

XS⚠️ ◾ Structural Improvements#784
muiriswoulfe wants to merge 3 commits intomainfrom
refactor/structural-improvements

Conversation

@muiriswoulfe
Copy link
Copy Markdown
Member

@muiriswoulfe muiriswoulfe commented Apr 10, 2026

Summary

  • CodeMetrics initialization rework: Replace boolean _isInitialized guard with a stored promise lock (_initializePromise) to ensure concurrent callers share a single initialization and errors propagate correctly.
  • Defensive copies: getFilesNotRequiringReview() and getDeletedFilesNotRequiringReview() now return shallow copies to prevent callers from mutating internal state.
  • URL parsing in gitHubReposInvoker: Replace manual split("/") URL parsing in initializeForAzureDevOps() with new URL() for safer, more robust parsing. Adds test for non-parseable URLs.
  • Remove unnecessary Promise.resolve() wrapping: Simplify isAccessTokenAvailable() in gitHubReposInvoker.ts and exec() in azurePipelinesRunnerInvoker.ts by removing redundant Promise.resolve() in async methods.
  • User agent constant: Extract hardcoded "PRMetrics/v1.7.13" user agent string into constants.ts as a single source of truth.
  • Deduplicate file extensions: Remove 7 duplicate entries (fcgi, inc, h, cgi, spec) from inputsDefault.ts code file extensions list.
  • Use path.extname() for extension extraction: Replace manual lastIndexOf(".")/substring() logic in matchFileExtension() with path.extname().
  • Extract numeric environment variable helper: Add getNumericEnvironmentVariable() in gitInvoker.ts to eliminate repeated get-env/check-undefined/check-numeric pattern in pullRequestIdForAzurePipelines.
  • Extract initializeNumeric() helper: Add a generic numeric initialisation helper in inputs.ts to deduplicate initializeBaseSize() and initializeGrowthRate(). initializeTestFactor() retains its special-case handling for zero.
  • Array join in getMetricsComment(): Replace string concatenation with parts.join("") for cleaner construction of the metrics comment.

@muiriswoulfe
Copy link
Copy Markdown
Member Author

muiriswoulfe commented Apr 10, 2026

PR Metrics

Thanks for keeping your pull request small.
⚠️ Consider adding additional tests.

Lines
Product Code 159
Test Code 29
Subtotal 188
Ignored Code -
Total 188

Metrics computed by PR Metrics. Add it to your Azure DevOps and GitHub PRs!

@muiriswoulfe muiriswoulfe changed the title Structural Improvements XS⚠️ ◾ Structural Improvements Apr 10, 2026
@muiriswoulfe
Copy link
Copy Markdown
Member Author

Super-linter summary

Language Validation result
BIOME_LINT Pass ✅
CHECKOV Pass ✅
EDITORCONFIG Pass ✅
GITHUB_ACTIONS Pass ✅
GITHUB_ACTIONS_ZIZMOR Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
JSCPD Pass ✅
JSON_PRETTIER Pass ✅
MARKDOWN Pass ✅
MARKDOWN_PRETTIER Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
TYPESCRIPT_PRETTIER Pass ✅
XML Pass ✅
YAML Pass ✅
YAML_PRETTIER Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

@muiriswoulfe
Copy link
Copy Markdown
Member Author

Super-linter summary

Language Validation result
BIOME_LINT Pass ✅
CHECKOV Pass ✅
EDITORCONFIG Pass ✅
GITHUB_ACTIONS Pass ✅
GITHUB_ACTIONS_ZIZMOR Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
JSCPD Pass ✅
JSON_PRETTIER Pass ✅
MARKDOWN Pass ✅
MARKDOWN_PRETTIER Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
TYPESCRIPT_PRETTIER Pass ✅
XML Pass ✅
YAML Pass ✅
YAML_PRETTIER Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

@muiriswoulfe
Copy link
Copy Markdown
Member Author

Super-linter summary

Language Validation result
BIOME_LINT Pass ✅
CHECKOV Pass ✅
EDITORCONFIG Pass ✅
GITHUB_ACTIONS Pass ✅
GITHUB_ACTIONS_ZIZMOR Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
JSCPD Pass ✅
JSON_PRETTIER Pass ✅
MARKDOWN Pass ✅
MARKDOWN_PRETTIER Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
TYPESCRIPT_PRETTIER Pass ✅
XML Pass ✅
YAML Pass ✅
YAML_PRETTIER Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

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

This PR applies a set of small structural/idiomatic refactors across PR Metrics’ task implementation (GitHub + Azure Pipelines), aiming to improve robustness (URL parsing, initialization concurrency), reduce duplication, and prevent accidental state mutation.

Changes:

  • Refactors initialization and helper logic (promise-lock initialization in CodeMetrics, numeric initialization helper in Inputs, numeric env-var helper in GitInvoker).
  • Improves safety/maintainability (defensive copies for internal arrays, URL parsing for repo URIs, extracted userAgent constant, extension list dedupe, path.extname() usage).
  • Minor idiom cleanups (remove redundant Promise.resolve(), build comment via join("")).

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/task/tests/repos/gitHubReposInvoker.spec.ts Adds coverage for non-parseable repo URI when running on Azure Pipelines.
src/task/src/utilities/constants.ts Introduces a shared userAgent constant for GitHub API calls.
src/task/src/runners/azurePipelinesRunnerInvoker.ts Simplifies exec() return by removing redundant Promise.resolve() in an async method.
src/task/src/repos/gitHubReposInvoker.ts Uses shared userAgent; replaces manual URI splitting with new URL() parsing for Azure Pipelines initialization; removes redundant Promise.resolve().
src/task/src/pullRequests/pullRequestComments.ts Refactors comment construction to use parts.join("") instead of string concatenation.
src/task/src/metrics/inputsDefault.ts Removes duplicate file extensions from default code-extension list.
src/task/src/metrics/inputs.ts Deduplicates numeric input parsing/validation via initializeNumeric().
src/task/src/metrics/codeMetrics.ts Reworks initialization to a shared promise; returns defensive copies of arrays; switches extension extraction to path.extname().
src/task/src/git/gitInvoker.ts Adds getNumericEnvironmentVariable() helper to reduce repeated env-var parsing/validation logic.

Comment on lines 288 to 292
private matchFileExtension(fileName: string): boolean {
this._logger.logDebug("* CodeMetrics.matchFileExtension()");

const fileExtensionIndex: number = fileName.lastIndexOf(".");
const fileExtension: string = fileName
.substring(fileExtensionIndex + 1)
.toLowerCase();
const fileExtension: string = path.extname(fileName).slice(1).toLowerCase();
const result: boolean = this._inputs.codeFileExtensions.has(fileExtension);
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

path.extname() returns an empty string for dotfiles like .env, so fileExtension becomes "" and these files will never match even though InputsDefault.codeFileExtensions includes "env". This is a behavior change vs the previous lastIndexOf('.') logic and likely causes .env-style files to be incorrectly excluded from metrics. Consider special-casing dotfiles (e.g., when extname is empty and the basename starts with a single '.') or adding a fallback extraction so .env maps to env, and add/adjust a unit test to lock in the intended behavior.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants