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
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Make Github ignore the designs folder when determining repo language
flow/designs/src/* linguist-vendored
flow/scripts/variables.json linguist-generated=true

# Byte-for-byte copies of OpenROAD files, regenerated by
# docs/scripts/refresh_openroad_docs.py. Upstream's trailing whitespace must
# survive verbatim, or the refresh is no longer idempotent and the vendored
# copies stop matching the commit SOURCE.json pins.
docs/_vendor/openroad/** -whitespace
7 changes: 7 additions & 0 deletions .github/workflows/github-actions-cron-update-OR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ jobs:
echo "::set-output name=has_update::$(git --no-pager diff --name-only origin/master..HEAD)"
git checkout master
git pull
- name: Refresh vendored OpenROAD docs
# docs/conf.py reads docs/_vendor/openroad/ instead of downloading from
# GitHub while Sphinx runs, so the vendored copies must be re-taken at
# the new submodule SHA. Running it here puts the docs refresh in the
# same commit as the submodule bump, which is what
# docs/scripts/check_vendored_docs.py asserts.
run: python3 docs/scripts/refresh_openroad_docs.py
- if: "steps.remote-update.outputs.has_update != ''"
name: Create Draft PR
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
Expand Down
115 changes: 115 additions & 0 deletions .github/workflows/github-actions-push-vendored-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Push refreshed vendored OpenROAD docs

on:
workflow_run:
workflows: ["Refresh vendored OpenROAD docs on submodule bump"]
types: [completed]
workflow_dispatch:
inputs:
run_id:
description: "Run ID of the producer workflow to pull the patch from"
required: true
type: string

permissions:
contents: read
pull-requests: write

jobs:
push-refresh:
# workflow_run always executes in the base repo's trusted context (with
# secrets), even when the triggering pull_request run read a fork's PR --
# this is the standard safe split for acting-with-secrets on fork PR
# content: https://docs.github.com/actions/security-guides/... . Pushing
# onto a fork branch needs a real maintainer identity (the openroad-ci
# bot's DOCS_BOT_PAT); the default GITHUB_TOKEN can never write to a fork
# regardless of trigger type. That only works if the PR left "Allow edits
# by maintainers" enabled -- if not, the push step below fails and we
# fall back to commenting the patch on the PR instead (using the default
# token, which can always comment even on a fork PR -- no PAT needed for
# that half). workflow_dispatch is a manual escape hatch: workflow_run is
# only evaluated from the workflow file on the default branch, so it
# can't be exercised pre-merge or retried by hand without this.
if: >-
github.repository == 'The-OpenROAD-Project/OpenROAD-flow-scripts' &&
(
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
)
runs-on: ubuntu-latest
steps:
- name: Download patch + context
id: dl
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.inputs.run_id || github.event.workflow_run.id }}
pattern: vendor-refresh-*
path: artifact

- name: No artifact -- nothing to do
if: steps.dl.outcome != 'success'
run: echo "no vendor-refresh patch produced; docs already in sync."

- name: Read PR context
if: steps.dl.outcome == 'success'
id: ctx
run: |
json_file=$(find artifact -name pr-context.json)
patch_file=$(find artifact -name vendor-refresh.patch)
echo "number=$(jq -r .number "$json_file")" >> "$GITHUB_OUTPUT"
echo "head_sha=$(jq -r .head_sha "$json_file")" >> "$GITHUB_OUTPUT"
echo "head_ref=$(jq -r .head_ref "$json_file")" >> "$GITHUB_OUTPUT"
echo "head_repo=$(jq -r .head_repo "$json_file")" >> "$GITHUB_OUTPUT"
echo "patch_file=$patch_file" >> "$GITHUB_OUTPUT"

- name: Push refresh onto the PR branch
if: steps.dl.outcome == 'success'
id: push
continue-on-error: true
env:
DOCS_BOT_PAT: ${{ secrets.DOCS_BOT_PAT }}
HEAD_REPO: ${{ steps.ctx.outputs.head_repo }}
HEAD_SHA: ${{ steps.ctx.outputs.head_sha }}
HEAD_REF: ${{ steps.ctx.outputs.head_ref }}
PATCH_FILE: ${{ steps.ctx.outputs.patch_file }}
run: |
git clone --depth 50 \
"https://x-access-token:${DOCS_BOT_PAT}@github.com/${HEAD_REPO}.git" \
work
cd work
git checkout "$HEAD_SHA"
git config user.name "openroad-ci"
git config user.email "openroad-ci@users.noreply.github.com"
git apply --index "../${PATCH_FILE}"
git commit --signoff -m "docs: refresh vendored OpenROAD docs for submodule bump"
git push origin "HEAD:${HEAD_REF}"

- name: Comment patch if push failed
if: steps.dl.outcome == 'success' && steps.push.outcome != 'success'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.ctx.outputs.number }}
PATCH_FILE: ${{ steps.ctx.outputs.patch_file }}
run: |
{
echo "Automatic vendored-docs refresh could not be pushed to this PR branch"
echo "(most likely because **Allow edits by maintainers** is off)."
echo
echo "Run this locally and push the result:"
echo '```'
echo "python3 docs/scripts/refresh_openroad_docs.py"
echo '```'
echo
echo "Or apply this patch directly:"
echo '<details><summary>vendor-refresh.patch</summary>'
echo
echo '```diff'
cat "$PATCH_FILE"
echo '```'
echo '</details>'
} > comment.md
gh pr comment "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--body-file comment.md
71 changes: 71 additions & 0 deletions .github/workflows/github-actions-refresh-vendored-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Refresh vendored OpenROAD docs on submodule bump

on:
pull_request:
paths:
- tools/OpenROAD

permissions:
contents: read

jobs:
build-refresh:
# Runs read-only against the PR's own head (fork or same-repo, either
# way) and never touches secrets or push access -- see
# github-actions-push-vendored-docs.yml for the trusted half that acts on
# this job's output. Only run in the org-owned repo itself, and skip our
# own bot's push-back retrigger (idempotent no-op anyway, this just saves
# the run).
if: >-
github.repository == 'The-OpenROAD-Project/OpenROAD-flow-scripts' &&
github.actor != 'openroad-ci'
runs-on: ${{ vars.USE_SELF_HOSTED == 'true' && 'self-hosted' || 'ubuntu-latest' }}
steps:
- name: Check out PR head
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.pull_request.head.sha }}
submodules: true

- name: Refresh vendored OpenROAD docs
run: python3 docs/scripts/refresh_openroad_docs.py

- name: Check vendored docs are in sync
run: python3 docs/scripts/check_vendored_docs.py

- name: Build patch if changed
id: diff
run: |
if [ -n "$(git status --porcelain -- docs/_vendor/openroad)" ]; then
git diff -- docs/_vendor/openroad > vendor-refresh.patch
echo "has_diff=true" >> "$GITHUB_OUTPUT"
else
echo "vendored docs already match the new submodule SHA; nothing to push."
echo "has_diff=false" >> "$GITHUB_OUTPUT"
fi

- name: Save PR context
if: steps.diff.outputs.has_diff == 'true'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
run: |
jq -n \
--arg number "$PR_NUMBER" \
--arg head_sha "$PR_HEAD_SHA" \
--arg head_ref "$PR_HEAD_REF" \
--arg head_repo "$PR_HEAD_REPO" \
'{number: ($number | tonumber), head_sha: $head_sha, head_ref: $head_ref, head_repo: $head_repo}' \
> pr-context.json

- name: Upload patch + context
if: steps.diff.outputs.has_diff == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: vendor-refresh-${{ github.event.pull_request.number }}
path: |
vendor-refresh.patch
pr-context.json
retention-days: 1
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,15 @@ perf.data
perf.data.old

# documentation specific
# Everything below is generated by docs/conf.py during `make html`; the sources
# are docs/index.md, ../README.md and docs/_vendor/openroad/ (see
# docs/_vendor/openroad/README.md).
docs/main
docs/build
SupportedOS.md
index2.md
Manpage.md
mainREADME.md
docs/contrib/GitGuide.md
build
.scala-build/
.bsp/
Expand All @@ -107,4 +110,5 @@ MODULE.bazel.lock

# python venv
venv/
.venv/
tmp/
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3.10"
python: "3.12"

# Build documentation in the "docs/" directory with Sphinx
sphinx:
Expand Down
5 changes: 0 additions & 5 deletions Jenkinsfile

This file was deleted.

10 changes: 9 additions & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@ SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR =
BUILDDIR = build
# Read the Docs builds with 3.12 (see .readthedocs.yaml); override if you want
# a specific interpreter locally.
PYTHON ?= python3

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile
# Create a local virtualenv and install the hash-pinned doc-build dependencies.
venv:
$(PYTHON) -m venv .venv
.venv/bin/pip install -r requirements_lock.txt

.PHONY: help Makefile venv

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
Expand Down
27 changes: 16 additions & 11 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,33 @@ repository and is published at

### Requires

- Python 3.10 — the version Read the Docs builds with (see `.readthedocs.yaml`).
The pinned Sphinx release does not run on Python 3.13 or newer.
- Python 3.10+ (tested through 3.14) — Read the Docs builds with 3.12 (see
`.readthedocs.yaml`); any recent `python3` on PATH works locally.
- `pip`
- `virtualenv` (or the standard-library `venv`)

### Install prerequisites

Run from the repository root:
Run from `docs/`:

``` shell
virtualenv .venv
make venv
source .venv/bin/activate
pip install -r docs/requirements_lock.txt
```

`make venv` just runs `python3 -m venv .venv && .venv/bin/pip install -r
requirements_lock.txt`; pass `PYTHON=/path/to/python3` to use a specific
interpreter instead of whatever `python3` resolves to on your PATH.

`docs/requirements_lock.txt` is the hash-pinned lock file that Read the Docs
installs, so a local build matches the published one. The direct dependencies
are listed in `docs/requirements.in`; after editing that file, regenerate the
lock with:
lock with [`uv`](https://docs.astral.sh/uv/) (`pip-compile` from `pip-tools`
is a documented alternative, but at time of writing has a compatibility bug
with recent `pip` releases):

``` shell
pip-compile --generate-hashes --output-file=docs/requirements_lock.txt docs/requirements.in
uv pip compile --upgrade --generate-hashes --output-file=docs/requirements_lock.txt docs/requirements.in
```

### Build
Expand Down Expand Up @@ -62,7 +67,7 @@ It exits non-zero when any link is unreachable.
`SupportedOS.md`, `Manpage.md`, `mainREADME.md`, and — because it is fetched
rather than authored here — the tracked file `contrib/GitGuide.md`. Do not
commit those changes; `git checkout docs/contrib/GitGuide.md` after a build.
- Always `rm -rf docs/build` before rebuilding. The output directory is
`build/`, but `conf.py`'s `exclude_patterns` only excludes `_build`, so a
second run picks up the Markdown files written under `build/html/` as if they
were source pages.
- `conf.py`'s `exclude_patterns` excludes `build` (the actual output directory
— Sphinx's own default is `_build`) and any local `.venv`/`venv`, so re-running
a build, or building from a checkout with a local virtualenv already in
`docs/`, does not pick that up as source content.
Loading
Loading