-
Notifications
You must be signed in to change notification settings - Fork 8
ci: enforce quarto extensions render only what they serve #442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -150,3 +150,65 @@ runs: | |
| exit 1 | ||
| fi | ||
| shell: bash | ||
|
|
||
| # The render-set guard below only applies to Quarto content. | ||
| - name: Detect Quarto appmode | ||
| id: quarto-appmode | ||
| run: | | ||
| APPMODE=$(jq -r '.metadata.appmode // ""' ./extensions/${{ inputs.extension-name }}/manifest.json) | ||
| if [[ "$APPMODE" == quarto-* ]]; then | ||
| echo "is-quarto=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "is-quarto=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
| shell: bash | ||
|
|
||
| - name: Set up Quarto | ||
| if: steps.quarto-appmode.outputs.is-quarto == 'true' | ||
| uses: quarto-dev/quarto-actions/setup@v2 | ||
|
|
||
| # Guards against the served-document bug (#392): Quarto renders every sibling | ||
| # Markdown file (e.g. CHANGELOG.md) as its own page, and with no pinned | ||
| # primary the default served document can silently flip to that page (e.g. | ||
| # CHANGELOG.html) instead of the entrypoint. Every build-time check stays | ||
| # green, so nothing else catches it. The standard is that a Quarto extension | ||
| # renders only what it serves: single-document content pins project.render to | ||
| # its entrypoint, while websites render their own pages. So this fails when a | ||
| # non-website extension renders a sibling Markdown page. | ||
| - name: Check Quarto render set | ||
| if: steps.quarto-appmode.outputs.is-quarto == 'true' | ||
| run: | | ||
| set -euo pipefail | ||
| EXT_DIR=./extensions/${{ inputs.extension-name }} | ||
|
|
||
| # Without a _quarto.yml the directory is not a project, so Connect renders | ||
| # only the entrypoint and no sibling Markdown becomes a page. | ||
| if ! INSPECT=$(quarto inspect "$EXT_DIR" 2>/dev/null); then | ||
| echo "Not a Quarto project; only the entrypoint renders. OK." | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Websites legitimately render many pages and serve index.html by convention. | ||
| PROJECT_TYPE=$(jq -r '.config.project.type // "default"' <<< "$INSPECT") | ||
| if [ "$PROJECT_TYPE" == "website" ]; then | ||
| echo "Website project; many pages are expected. OK." | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Rendered input basenames. | ||
| INPUTS=$(jq -r '.files.input[] | split("/") | last' <<< "$INSPECT") | ||
| COUNT=$(grep -c . <<< "$INPUTS") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there are no input matches I think this will |
||
|
|
||
| # A lone document is unambiguously the served document. Otherwise a | ||
| # rendered sibling Markdown file (Quarto ignores README.md) is a stray | ||
| # page that could become the served document. | ||
| STRAY_MD=$(grep -iE '\.md$' <<< "$INPUTS" | grep -viE '^README\.md$' || true) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't checking for stray |
||
| if [ "$COUNT" -gt 1 ] && [ -n "$STRAY_MD" ]; then | ||
| echo "Error: Quarto extension '${{ inputs.extension-name }}' renders sibling Markdown page(s):" | ||
| echo "$STRAY_MD" | ||
| echo "Pin the entrypoint in _quarto.yml (project.render) so only it renders and becomes the served document." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "No stray Markdown pages render. OK." | ||
| shell: bash | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ jobs: | |
| _infra: | ||
| - integration/** | ||
| - .github/actions/connect-integration-test/** | ||
| - .github/actions/lint-extension/** | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be added to the complex-extension block too? |
||
| - .github/workflows/connect-integration-tests.yml | ||
| - .github/workflows/extensions.yml | ||
| quarto-stock-report-python: extensions/quarto-stock-report-python/** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| project: | ||
| # Render only the document so it is the unambiguous primary document. | ||
| # Without this, Quarto also renders sibling Markdown (e.g. CHANGELOG.md) | ||
| # and the default served document can become that file instead. | ||
| render: | ||
| - index.qmd |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,7 @@ | ||
| project: | ||
| title: Stock Report | ||
| # Render only the report so it is the unambiguous primary document. | ||
| # Without this, Quarto also renders sibling Markdown (e.g. CHANGELOG.md) | ||
| # and the default served document can become that file instead. | ||
| render: | ||
| - index.qmd |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,7 @@ | ||
| project: | ||
| title: Stock Report | ||
| # Render only the report so it is the unambiguous primary document. | ||
| # Without this, Quarto also renders sibling Markdown (e.g. CHANGELOG.md) | ||
| # and the default served document can become that file instead. | ||
| render: | ||
| - index.qmd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any
quarto inspectfailure will result in "not a Quarto project" so if the_quarto.ymlis incorrect, like missing a semicolon inrender:quarto inspectwill error, but this will pass.I think that this is tricky to do right though, maybe this is a good first pass that we improve over time.