Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,53 @@ jobs:
env: pr_preview
ref: ${{ github.event.pull_request.head.ref }}

- name: Get all changed files
id: changed-files
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
CHANGED_FILES="$(node scripts/ci/determine-changed-files.ts "${{ github.event.number }}")"
{
echo "ALL_CHANGED_FILES<<__GH_OUTPUT__"
printf '%s\n' "$CHANGED_FILES"
echo "__GH_OUTPUT__"
} >> "$GITHUB_OUTPUT"

- name: Determine changed content files
env:
GH_TOKEN: ${{ github.token }}
CHANGED_FILES: ${{ steps.changed-files.outputs.ALL_CHANGED_FILES }}
# If changing these regexes, test them on https://regex101.com/ with the
# following paths (you can paste the block in and uncomment it):
# Add new tests if necessary
CONTENT_FILE_REGEX: (docs|learning)(?!\/api)\/.*\.(mdx|ipynb)
# -- Should match:
# docs/guides/thing.ipynb
# docs/guides/thing.mdx
# learning/courses/my-course/introduction.ipynb
#
# -- Should not match:
# docs/guides/_toc.json
# docs/api/qiskit/index.mdx
# scripts/nb-tester/example-notebook.ipynb
id: changed-content-files
run: |
CHANGED_CONTENT_FILES=$(echo "${CHANGED_FILES[@]}" | grep -P $CONTENT_FILE_REGEX || true)
mkdir -p .github/outputs
echo "Detected these changed content files:"
echo $CHANGED_CONTENT_FILES
echo $CHANGED_CONTENT_FILES >> .github/outputs/changed-content-files.txt

- name: Build static site
run: >
scripts/pr-previews/builder.py
${{ env.PR_PREVIEW_PATH }}
--basepath /documentation/${{ env.PR_PREVIEW_PATH }}

- name: Delete temp files
# Otherwise this gets pushed to the gh-pages branch
run: rm -r .github/outputs

- name: Deploy to GitHub Pages
run: scripts/pr-previews/deploy.py ${{ env.PR_PREVIEW_PATH }}

Expand Down
75 changes: 63 additions & 12 deletions scripts/pr-previews/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,16 @@ def main() -> None:
write_proof_of_concept(args.dest)
return

with setup_dir() as dir:
try:
lines = (
Path(".github/outputs/changed-content-files.txt").read_text().split("\n")
)
changed_content_files = set(line for line in lines if line != "")
except FileNotFoundError:
logger.info("No changed files detected, will build all pages")
changed_content_files: set[str] = set()

with setup_dir(changed_content_files) as dir:
yarn_build(dir, args.basepath)
save_output(dir, args.dest)
write_timestamp(args.dest)
Expand Down Expand Up @@ -105,33 +114,75 @@ def save_output(root_dir: Path, dest: Path) -> None:


@contextmanager
def setup_dir() -> Iterator[Path]:
def setup_dir(changed_content_files: set[str]) -> Iterator[Path]:
with TemporaryDirectory() as _tempdir:
root_dir = Path(_tempdir)
logger.info(f"Using tmpdir {root_dir}")

_copy_local_content(root_dir)
_copy_local_content(root_dir, changed_content_files)
_extract_docker_files(root_dir)
yield root_dir


def _copy_local_content(root_dir: Path) -> None:
# We intentionally don't copy over API docs to speed up the build.
def _copy_local_content(root_dir: Path, changed_files: set[str]) -> None:

def ignore_contents(dir: str, contents: list[str]) -> list[str]:
"""For input to shutil.copytree. This function takes the directory path
(such as `docs/guides`) and a list of file and folder names (entries) in
that directory (such as `["api", "index.mdx", ... ]`). It should output a list
of entries to ignore.
"""
ignores = []

# Don't copy any entries named "api". This has the effect of ignoring
# any paths matching "/api/". We intentionally don't copy over API docs
# to speed up the build.
if "api" in contents:
ignores.append("api")

# No changed files means we should copy over everything.
if len(changed_files) == 0:
return ignores

for entry in contents:
full_path = f"{dir}/{entry}"

# Always copy over the `public` folder as its contents could be used
# anywhere. TODO: Maybe make this more selective?
if full_path.startswith("public"):
continue

# We also need to copy over `_toc.json` used by any changed files.
# Copytree should only reach these files if a sibling or child of
# the current directory contains a changed file.
if entry == "_toc.json":
continue

# We also need to copy over the index files because the app doesn't
# build without them
if entry.startswith("index."):
continue

# Finally, include files that were directly changed.
if any(file.startswith(full_path) for file in changed_files):
continue

# Ignore everything else
ignores.append(entry)

return ignores

for dir in [
"docs/guides",
"docs/tutorials",
"public/docs/images/tutorials",
"docs",
"public",
"learning",
"public/docs/images/guides",
"public/docs/images/qiskit-patterns",
"public/learning",
]:
dest = (
root_dir / "packages/preview" / dir
if dir.startswith("public")
else root_dir / f"content/{dir}"
)
shutil.copytree(dir, dest)
shutil.copytree(dir, dest, ignore=ignore_contents)

for fp in [
"docs/responsible-quantum-computing.mdx",
Expand Down