Skip to content

Add deployment summary to the job summary and pull request comment - #279

Open
chhateauuu wants to merge 12 commits into
masterfrom
t-achhatkuli/dev/pr-deploy-summary
Open

Add deployment summary to the job summary and pull request comment#279
chhateauuu wants to merge 12 commits into
masterfrom
t-achhatkuli/dev/pr-deploy-summary

Conversation

@chhateauuu

Copy link
Copy Markdown

Summary

When sql-action deploys a database, the details of what actually changed are only visible in the build logs. A reviewer sees a green check and has to open the run and read the logs to learn what happened to the database.

This PR makes the action publish a concise deployment summary of what the deployment changed. It is written to the GitHub Actions job summary and, on pull requests, posted as a single auto-updating sticky comment. It reports the objects created, altered, and dropped, warns about possible data loss, and includes the full deployment T-SQL in a collapsible section.

The information already exists: SqlPackage computes the change set during every publish. This PR captures the deployment report and script it produces, parses them, formats a summary, and publishes it. No deployment logic is added or changed.

code-walkthrough.md

What it looks like

On a pull request that changes the schema, the action posts a summary like this:

SQL deployment summary

Published Database.sqlproj to myserver / mydb — 10 changes (5 created, 4 altered, 1 dropped), 3 data-loss warnings

A metadata table (action, target, duration, triggering user, commit, options), followed by:

Changes (10)

By-type and by-schema breakdowns, then collapsible Created / Altered / Dropped sections listing each object and its type.

Possible data loss (3)

  • The column [dbo].[Messages].[LegacyFlag] is being dropped, data loss could occur.
  • The table [dbo].[OldAudit] is being dropped, data loss could occur.

A collapsible block with the full deployment T-SQL script.

What changed

  • New src/DeploymentReport.ts: parses the SqlPackage deployment report XML into operations and alerts. Tolerant of missing or malformed input.
  • New src/DeploymentSummary.ts: a pure function that renders the summary Markdown.
  • New src/Reporter.ts: writes the job summary, posts or updates the sticky PR comment, and sets outputs. Best-effort; it can never fail a deployment.
  • src/AzureSqlAction.ts: during a Publish, captures the deployment report and script (respecting any caller-supplied paths) and returns their locations.
  • src/main.ts: measures the deploy duration and invokes the reporter after a successful deploy.
  • action.yml and README.md: document the new inputs and outputs.

The change is organized into small, logical commits so it can be reviewed step by step.

New inputs (all optional)

Input Default Description
summary true Write the deployment summary to the job summary.
comment-pr auto Post the summary as a sticky PR comment. One of off, auto, always.
github-token ${{ github.token }} Token used to post the comment.

New outputs

changes-detected, objects-changed, deployment-report-path, deployment-script-path.

Behavior and safety

  • Backward compatible. No existing input, output, or deploy behavior changes. Existing workflows run identically with no edits.
  • Reporting is fully guarded. Any error is logged as a warning; the deployment result is never affected.
  • No secrets. The target is shown as server and database only; user id and password are already masked and never appear in the summary.
  • The comment requires pull-requests: write. When the token or permission is missing, the action logs a warning and falls back to the job summary.
  • Object rows and the script are truncated with a clear marker so a comment cannot become excessively large; table cells escape pipe characters.

Compatibility notes

  • Two dependencies were added: fast-xml-parser (report parsing) and @actions/github (comment posting). @actions/github is pinned to the v6 CommonJS line for compatibility with the existing webpack build.
  • The committed lib/main.js grows from about 284 KB to 860 KB, driven mainly by the GitHub API client.
  • Open question: comment-pr defaults to auto. If a more conservative default is preferred, it can default to off (opt-in). This is a one-line change; happy to adjust.

Testing

  • New Jest suites cover the parser (real sample report plus single-node, empty, blank, and malformed input), the renderer (grouping, counts, breakdowns, data-loss, truncation, pipe escaping, byte-order-mark handling, and a check that no password is rendered), the reporter (comment created when absent, updated when present, warn-without-fail on missing token, non-PR, or permission errors), and the capture argument injection.
  • Full suite green at 177 tests; npm run build succeeds and the committed bundle is up to date.

Copilot AI left a comment

Copy link
Copy Markdown

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 adds post-deployment reporting to sql-action by capturing SqlPackage’s deployment report/script, converting them into a concise Markdown summary, and publishing that summary to the GitHub Actions job summary and (optionally) a sticky pull request comment.

Changes:

  • Capture SqlPackage deployment report XML and deployment script during publish, and return their paths from the action execution.
  • Parse the deployment report and render a Markdown “deployment summary” including change breakdowns, data-loss warnings, and an embedded script section.
  • Add a reporter that writes the job summary, upserts a sticky PR comment, and sets new outputs describing changes and artifact paths.

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/Reporter.ts Implements summary publishing (job summary + sticky PR comment) and sets new outputs.
src/main.ts Measures deploy duration and invokes the reporter; enables deployment report capture in inputs.
src/DeploymentSummary.ts Renders GitHub-flavored Markdown summary (headline, metadata, changes, alerts, script).
src/DeploymentReport.ts Parses SqlPackage deployment report XML into operations and alerts.
src/AzureSqlAction.ts Adds optional capture of deployment report/script paths for publish executions.
README.md Documents new inputs/outputs and deployment summary behavior.
package.json Adds dependencies for GitHub API usage and XML parsing.
package-lock.json Locks the dependency graph for newly added packages.
lib/main.js.LICENSE.txt Updates bundled-license notices due to added dependencies.
action.yml Adds new inputs/outputs and continues to point to the bundled JS entrypoint.
tests/Reporter.test.ts Adds tests for summary publishing and sticky comment upsert behavior.
tests/main.test.ts Updates mocks to reflect execute() now returning an action result object.
tests/DeploymentSummary.test.ts Adds tests for Markdown rendering, grouping, truncation, and escaping.
tests/DeploymentReport.test.ts Adds tests for report XML parsing and malformed/edge inputs.
tests/AzureSqlAction.test.ts Adds tests verifying capture arg injection and path reuse behavior.
testdata/deployReport.xml Adds a representative deployment report fixture for parser tests.

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

Comment thread src/Reporter.ts
Comment thread src/Reporter.ts
Comment thread src/main.ts
Comment thread src/Reporter.ts
Comment thread src/Reporter.ts
Comment thread package.json Outdated
Comment thread src/DeploymentReport.ts Outdated
Comment thread src/Reporter.ts
Comment thread __tests__/Reporter.test.ts
Comment thread README.md
Comment thread lib/main.js.LICENSE.txt
@@ -0,0 +1,3 @@
/*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's with this file?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It is auto-generated by webpack's license-extraction step. Adding @actions/github pulls in node-fetch, which includes formdata-polyfill, and webpack collects those MIT notices into the main.js.LICENSE.txt sidecar next to the bundle. It is just third-party license attribution for the newly bundled dependency and is the standard output. Happy to change the bundling if you would prefer it not be emitted.

@Benjin

Benjin commented Jul 29, 2026

Copy link
Copy Markdown
Member

@chhateauuu can you go through the copilot suggestions, determine which are valid, and either address or close them all?

Comment thread src/DeploymentReport.ts
try {
parsed = parser.parse(xml);
} catch {
return { operations: [], alerts: [] };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the behavior if parsing fails? Does it create a status comment saying it failed, or do we swallow failures?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

We swallow it by design. Reporting is best-effort and must never fail a deployment: if the report XML is missing, blank, or malformed, the parser returns an empty result, the summary omits the changes section, and the deploy is unaffected. Problems are logged via core.debug/core.warning, and the whole reporter is wrapped so an error there cannot fail the run. It does not post a "failed" status comment. If you would like a visible "deployment report could not be parsed" note in the summary for transparency, that is an easy follow-up.

Comment thread src/DeploymentReport.ts Outdated
Comment thread src/DeploymentSummary.ts Outdated
Benjin
Benjin previously approved these changes Jul 29, 2026
Comment thread src/DeploymentSummary.ts Outdated
@Benjin
Benjin self-requested a review July 29, 2026 21:56
Copilot suggestions:
- _getBooleanInput returns the default for empty or unrecognized values
- _setOutputs only sets change outputs when a report was captured
- gate deployment-report capture on reporting being enabled
- paginate the sticky-comment lookup so it is found past 100 comments
- redact secret-looking arguments from the summary
- pin @actions/github to 6.0.0
- remove the unused EMPTY_REPORT constant

Reviewer notes:
- friendlyType uses startsWith instead of a regex
- Dropped icon changed to a cross mark
- use string methods (replaceAll, trimEnd, startsWith) where a regex was not needed

Add es2019/es2021 string libs, update tests, and rebuild the bundle.
Comment thread src/Reporter.ts Outdated
* Publishes the action outputs describing the deployment.
*/
private static _setOutputs(context: SummaryContext, result: IActionResult): void {
if (context.report) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should we still set these two when there's no report?

For .sql deployments IIRC there's no report, so these outputs never get set and anyone checking changes-detected == 'false' in their workflow gets an empty string back, their step just silently doesn't run.

action.yml says it's always 'true' or 'false', and it used to be. Maybe const operations = context.report?.operations ?? [] and set them unconditionally?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good call, you're right. Reverted to setting them unconditionally with const operations = context.report?.operations ?? [], so .sql and other no-report runs return false/0 instead of an empty string and the documented output contract holds. Thanks for catching that.

Per code-owner review: set changes-detected and objects-changed
unconditionally (false/0 when no report is captured) so .sql and
other no-report runs return 'false' instead of an empty string,
matching the action.yml output contract.
@ssreerama
ssreerama self-requested a review July 30, 2026 21:50
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.

4 participants