Skip to content

Replace monolithic docs workflow with staged deployment system#362

Merged
mattleibow merged 14 commits intomainfrom
copilot/setup-staging-system-one-more-time
Feb 26, 2026
Merged

Replace monolithic docs workflow with staged deployment system#362
mattleibow merged 14 commits intomainfrom
copilot/setup-staging-system-one-more-time

Conversation

Copy link
Contributor

Copilot AI commented Feb 25, 2026

  • Remove old .github/workflows/builds-docs.yml
  • Create merged docs-deploy.yml, docs-cleanup-staging-pr.yml, docs-go-live.yml
  • Fix docs/docfx.jsonnet9.0net10.0
  • Add docs-deploy-fork-pr.yml — secure fork PR staging via workflow_run
  • Security hardening — least-privilege permissions, env vars, PR number validation
  • Review feedback: PR_NUMBER validation, dedup comment, cleanup gh-pages guard, YAML parse fix
  • Build info via AssemblyMetadata MSBuild attribute + MainLayout.razor runtime read
  • Fix: restore missing @media (min-width: 641px) { in MainLayout.razor.css

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

- Add docs-deploy-main.yml: builds docs+Blazor on push to main and pushes to gh-pages root (preserving staging/)
- Add docs-deploy-staging-pr.yml: builds with staging base-href, deploys to staging/{pr}/, comments on PR
- Add docs-cleanup-staging-pr.yml: removes staging/{pr}/ when PR is closed
- Add docs-go-live.yml: deploys gh-pages branch to GitHub Pages via Actions
- Remove old builds-docs.yml (single-workflow monolith with peaceiris/actions-gh-pages)

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copilot AI changed the title [WIP] Add staging system for documentation deployment Replace monolithic docs workflow with main + PR staging system Feb 25, 2026
Copilot AI requested a review from mattleibow February 25, 2026 16:37
@mattleibow
Copy link
Collaborator

@copilot can you see if you can create a local composite action that runs the build so we don't need to duplicate the steps in the main vs staging. Or maybe see if there is a way to merge the deploy workflow and use different params/vars depending.

Please try the merge first as that is the preferred way

….yml

- Replace docs-deploy-main.yml and docs-deploy-staging-pr.yml with a
  unified docs-deploy.yml that handles both push-to-main and PR triggers
- A setup step computes artifact name, base href, and segmentCount based
  on github.event_name (push vs pull_request)
- Build job exposes outputs; deploy job uses conditional steps to either
  update gh-pages root (main) or staging/{pr}/ (PR)
- comment job runs only for staging on PR open/reopen
- Update docs-go-live.yml workflow_run list to reference new name

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 25, 2026

@copilot can you see if you can create a local composite action that runs the build so we don't need to duplicate the steps in the main vs staging. Or maybe see if there is a way to merge the deploy w...

Done in 7bdb9e1. Merged docs-deploy-main.yml and docs-deploy-staging-pr.yml into a single docs-deploy.yml.

A setup-build-variables step at the start of the build job branches on github.event_name to emit outputs (artifact_name, sample_base_href, sample_segment_count, is_staging, pr_number). The rest of the job consumes those outputs, so the build steps are written once. In the deploy job, two conditional steps replace the two separate deploy jobs — one runs when is_staging == 'false' (updates gh-pages root, preserving staging/), the other when is_staging == 'true' (writes to staging/{pr}/). The comment job condition now also guards on is_staging == 'true'. docs-go-live.yml is updated to reference the new "Docs - Deploy" workflow name.

@mattleibow
Copy link
Collaborator

@copilot can we use the Ubuntu-latest for the docs. Then also switch to use the Maui-android workload.

- Change build runner from windows-latest to ubuntu-latest
- Change workload from maui to maui-android
- Rewrite PowerShell copy/sed step as bash

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 25, 2026

@copilot can we use the Ubuntu-latest for the docs. Then also switch to use the Maui-android workload.

Done in 89984da. The build job now runs on ubuntu-latest with dotnet workload install maui-android. The PowerShell copy/rewrite step was also converted to bash to match the new Linux runner.

github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
@mattleibow mattleibow closed this Feb 25, 2026
@mattleibow mattleibow reopened this Feb 25, 2026
github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
@github-actions
Copy link

📖 Documentation Preview

The documentation for this PR has been deployed and is available at:

🔗 View Staging Documentation

🔗 View Staging Blazor Sample

This preview will be updated automatically when you push new commits to this PR.


This comment is automatically updated by the documentation staging workflow.

@mattleibow
Copy link
Collaborator

@copilot please review the workflow changes and let me know what issues there are. Also, please visit the staging links to make sure it all works.

Add job-level if to deploy job so it only runs for same-repo PRs and push/workflow_dispatch events. For fork PRs the GITHUB_TOKEN is read-only so git push to gh-pages would fail. comment job is naturally skipped when deploy is skipped (via needs).

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 25, 2026

@copilot please review the workflow changes and let me know what issues there are. Also, please visit the staging links to make sure it all works.

Review complete. One issue found and fixed (ea0c18f):

Fixed — Fork PR deploy would fail: The deploy job has permissions: contents: write and does git push origin gh-pages. For PRs from forked repos, GITHUB_TOKEN is read-only and the push would fail. Added a job-level if guard: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository. The comment job is naturally skipped when deploy is skipped (via needs).

Not fixed — pre-existing: docfx.json looks for **/bin/Release/net9.0/**.dll but the build step uses -f net10.0. This existed in the original builds-docs.yml and docfx silently skips missing metadata sources. Separately tracked.

Staging links: The docs-deploy.yml workflow runs on this PR itself (it matches the path filter .github/workflows/docs-deploy.yml). I wasn't able to reach the live staging URLs from my environment, so staging verification will need to be confirmed once the CI run on commit ea0c18f completes.

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:

  • mono.github.io
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)

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

@mattleibow
Copy link
Collaborator

@copilot there are now yaml errors:

Invalid workflow file: .github/workflows/docs-deploy-fork-pr.yml#L135
You have an error in your yaml syntax on line 135

Did you validate?

Copy link

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

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

Comment on lines +44 to +63
- name: Setup build variables
id: vars
env:
EVENT_NAME: ${{ github.event_name }}
PR_NUMBER: ${{ github.event.number }}
shell: bash
run: |
if [ "$EVENT_NAME" == "pull_request" ]; then
echo "artifact_name=staging-site-${PR_NUMBER}" >> $GITHUB_OUTPUT
echo "sample_base_href=/SkiaSharp.Extended/staging/${PR_NUMBER}/sample/" >> $GITHUB_OUTPUT
echo "sample_segment_count=4" >> $GITHUB_OUTPUT
echo "is_staging=true" >> $GITHUB_OUTPUT
echo "pr_number=${PR_NUMBER}" >> $GITHUB_OUTPUT
else
echo "artifact_name=main-site" >> $GITHUB_OUTPUT
echo "sample_base_href=/SkiaSharp.Extended/sample/" >> $GITHUB_OUTPUT
echo "sample_segment_count=2" >> $GITHUB_OUTPUT
echo "is_staging=false" >> $GITHUB_OUTPUT
echo "pr_number=" >> $GITHUB_OUTPUT
fi
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The PR_NUMBER should be validated before use to prevent creating malformed artifact names. If github.event.number is empty or not a valid positive integer, the artifact name "staging-site-${PR_NUMBER}" could become "staging-site-" or contain invalid characters. Add validation similar to what's done in other workflows (e.g., lines 151-155) to ensure PR_NUMBER is a positive integer before using it to construct the artifact name and paths.

Copilot uses AI. Check for mistakes.
Removing the indentation from template literal content in the previous
commit caused YAML parse errors: lines at column 0 inside a block scalar
(script: |) terminate the scalar prematurely.

Rewrote both comment bodies as string arrays joined with \n. This
sidesteps the YAML indentation constraint entirely while producing
identical output. Validated all 4 workflow files parse as valid YAML.

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 25, 2026

@copilot there are now yaml errors:

Invalid workflow file: .github/workflows/docs-deploy-fork-pr.yml#L135
...

Fixed in 3c6ac9a. The root cause: removing the indentation from the template literal content left those lines at column 0, which YAML interprets as terminating the block scalar (script: |) prematurely.

Replaced both comment bodies with [...].join('\n') arrays — every JS line stays indented at the block scalar level so YAML parses correctly, and the resulting PR comment has no extra whitespace. All four workflow files validated with python3 -c "import yaml; yaml.safe_load(...)" before pushing.

@mattleibow
Copy link
Collaborator

/azp run

github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
@mattleibow
Copy link
Collaborator

@copilot can we add a PR number and commit message to the docs page and sample app. For main builds, just use "main" and for PR use "PR #2468" as the "source branch" and then a commit has. Maybe something like "source" (dot) "commit" in the footer or something.

…alidate PR_NUMBER early

- docs-deploy.yml: validate PR_NUMBER as positive integer at start of
  pull_request branch in Setup build variables (before constructing
  artifact names and paths)
- docs-deploy.yml: emit source_label output ("main" or "PR #N")
- docs-deploy.yml: Build docs step uses jq to inject _appFooter into a
  temp docfx-build.json; runs docfx on the patched config. Footer shows
  "source: main · abc1234" or "source: PR #362 · abc1234"
- docs-deploy.yml: Copy Blazor sample step replaces BUILD_INFO_PLACEHOLDER
  in index.html with "main · abc1234" or "PR #362 · abc1234"
- samples/SkiaSharpDemo.Blazor/wwwroot/index.html: add #build-info div
  with BUILD_INFO_PLACEHOLDER (shows "BUILD_INFO_PLACEHOLDER" in local dev;
  replaced at deploy time)
- samples/SkiaSharpDemo.Blazor/wwwroot/css/app.css: add small fixed
  bottom-right badge style for #build-info

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 25, 2026

@copilot can we add a PR number and commit message to the docs page and sample app. For main builds, just use "main" and for PR use "PR #2468" as the "source branch" and then a commi...

Done in 841b7ce. Here's how it works in both surfaces:

Docs site (docfx footer) — the Build docs step uses jq to create a patched docfx-build.json with _appFooter injected into globalMetadata, then runs docfx on it. The footer reads:

  • Main builds: source: main · abc1234
  • PR builds: source: PR #362 · abc1234

Blazor sample (fixed badge) — added a <div id="build-info">BUILD_INFO_PLACEHOLDER</div> to wwwroot/index.html. The Copy Blazor sample step uses sed to replace the placeholder with the same SOURCE_LABEL · COMMIT_SHORT string at deploy time. A small semi-transparent fixed-position monospace badge appears in the bottom-right corner of every page (styled in app.css). Locally it shows the literal placeholder text, making it easy to spot during development.

PR_NUMBER early validation (review comment 2855820813) — also included in this commit: the regex guard ^[1-9][0-9]*$ is now applied at the very start of the pull_request branch in Setup build variables, before the PR number is used to construct artifact names or paths.

@mattleibow
Copy link
Collaborator

@copilot Maybe we can set assembly attributes on wasm app and use that. there are msbuild items/properties we could use. Then at runtime it could update something in the layout razor or something. Wherever. insead of editing the html.

….html

- SkiaSharpDemo.Blazor.csproj: add BuildInfo MSBuild property (defaults
  to "local") and an AssemblyAttribute item that bakes it into the
  assembly as AssemblyMetadataAttribute("BuildInfo", ...)
- Layout/MainLayout.razor: add @code block that reads BuildInfo from
  the executing assembly at runtime; renders it in a <footer class="build-info">
- Layout/MainLayout.razor.css: add .build-info footer style (right-aligned,
  monospace, muted, with top border)
- docs-deploy.yml: pass -p:BuildInfo="SOURCE_LABEL · SHA" to dotnet publish
  so CI bakes the correct label into the assembly; remove sed
  BUILD_INFO_PLACEHOLDER step and its env vars from the copy step
- wwwroot/index.html: remove BUILD_INFO_PLACEHOLDER div (no longer needed)
- wwwroot/css/app.css: remove #build-info fixed-position badge style

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 26, 2026

@copilot Maybe we can set assembly attributes on wasm app and use that. there are msbuild items/properties we could use. Then at runtime it could update something in the layout razor...

Done in d213119. Replaced the sed/placeholder approach with a proper MSBuild + runtime attribute flow:

SkiaSharpDemo.Blazor.csproj — added a BuildInfo MSBuild property (defaulting to "local") and an AssemblyAttribute item that bakes it into the compiled assembly as [assembly: AssemblyMetadata("BuildInfo", "...")].

CI (docs-deploy.yml)dotnet publish now receives -p:BuildInfo="PR #362 · abc1234" (or "main · abc1234"), so the value is baked in at compile time. The sed/placeholder lines are gone entirely.

MainLayout.razor — reads the attribute at runtime:

private string _buildInfo = typeof(App).Assembly
    .GetCustomAttributes<AssemblyMetadataAttribute>()
    .FirstOrDefault(a => a.Key == "BuildInfo")?.Value ?? "local";

Renders it as <footer class="build-info">@_buildInfo</footer> inside <main>.

MainLayout.razor.css — small right-aligned muted monospace footer style.

Local dev shows "local", deployed shows "main · abc1234" or "PR #362 · abc1234".

Copy link
Collaborator

@mattleibow mattleibow left a comment

Choose a reason for hiding this comment

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

@copilot what happened?

border-top: 1px solid #eee;
}

@media (min-width: 641px) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot what happened?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My edit that inserted .build-info accidentally swallowed the @media (min-width: 641px) { opening line, so all the responsive layout rules were unscoped. Fixed in 278019f — the @media line is restored at line 58, right after .build-info.

Comment on lines -112 to -114
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
text-align: start;
} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot what happened?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The #build-info block (fixed-position badge in index.html) was removed in d213119 as part of refactoring from the sed/placeholder approach to the AssemblyMetadata approach. The build info is now surfaced via a <footer class="build-info"> in MainLayout.razor using a Blazor-scoped CSS rule in MainLayout.razor.css, so the global app.css entry was no longer needed.

The previous edit that inserted .build-info accidentally dropped the
@media (min-width: 641px) { opening line, leaving the responsive layout
rules unscoped and causing the orphaned } at the end. Restored.

Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 26, 2026

@copilot what happened?

A CSS regression was introduced when inserting the .build-info rule — the @media (min-width: 641px) { opening line was accidentally dropped from MainLayout.razor.css, leaving the responsive layout rules unscoped. Fixed in 278019f.

github-actions bot pushed a commit that referenced this pull request Feb 26, 2026
@mattleibow mattleibow merged commit c05aed0 into main Feb 26, 2026
4 checks passed
@mattleibow mattleibow deleted the copilot/setup-staging-system-one-more-time branch February 26, 2026 01:27
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.

3 participants