Skip to content

Commit 3da7dab

Browse files
authored
renderdiff: enable update goldens on commit merge (#8771)
1 parent 1e2311d commit 3da7dab

File tree

9 files changed

+236
-51
lines changed

9 files changed

+236
-51
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: 'Get commit message'
2+
outputs:
3+
msg:
4+
value: ${{ steps.action_output.outputs.msg }}
5+
runs:
6+
using: "composite"
7+
steps:
8+
- name: Find commit message (on push)
9+
if: github.event_name == 'push'
10+
shell: bash
11+
run: |
12+
echo "${{ github.event.head_commit.message }}" >> /tmp/commit_msg.txt
13+
- name: Checkout code
14+
shell: bash
15+
id: checkout_code
16+
if: github.event_name == 'pull_request'
17+
run: |
18+
echo "hash=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
19+
git checkout ${{ github.event.pull_request.head.ref }}
20+
COMMIT_MESSAGE=$(git log -1)
21+
echo "${COMMIT_MESSAGE}" >> /tmp/commit_msg.txt
22+
- shell: bash
23+
id: action_output
24+
run: |
25+
DELIMITER="EOF_FILE_CONTENT_$(date +%s)" # Using timestamp to make it more unique
26+
echo "msg<<$DELIMITER" >> "$GITHUB_OUTPUT"
27+
cat /tmp/commit_msg.txt >> "$GITHUB_OUTPUT"
28+
echo "$DELIMITER" >> "$GITHUB_OUTPUT"
29+
- name: Uncheckout code
30+
shell: bash
31+
if: github.event_name == 'pull_request'
32+
run: |
33+
git checkout ${{ steps.checkout.outputs.hash }}

.github/workflows/postsubmit.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: 'Post-submit tasks'
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
push:
8+
branches:
9+
- main
10+
11+
jobs:
12+
update-renderdiff-goldens:
13+
name: update-renderdiff-goldens
14+
runs-on: 'ubuntu-24.04-4core'
15+
steps:
16+
- uses: actions/checkout@v4.1.6
17+
with:
18+
fetch-depth: 0
19+
- uses: ./.github/actions/linux-prereq
20+
- id: get_commit_msg
21+
uses: ./.github/actions/get-commit-msg
22+
- name: Prerequisites
23+
run: pip install tifffile numpy
24+
- name: Run update script
25+
env:
26+
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
27+
run: |
28+
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 test/renderdiff/src/commit_msg.py)
29+
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | tr -d 'commit ')
30+
if [[ "${GOLDEN_BRANCH}" != "main" ]]; then
31+
git config --global user.email "filament.bot@gmail.com"
32+
git config --global user.name "Filament Bot"
33+
git config --global credential.helper cache
34+
echo "branch==${GOLDEN_BRANCH}"
35+
echo "hash==${COMMIT_HASH}"
36+
python3 test/renderdiff/src/update_golden.py --branch=${GOLDEN_BRANCH} \
37+
--merge-to-main --filament-tag=${COMMIT_HASH} --golden-repo-token=${GH_TOKEN}
38+
fi

.github/workflows/presubmit.yml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ name: Presubmit
33
on:
44
push:
55
branches:
6-
- main
6+
- main
77
pull_request:
88
branches:
9-
- main
9+
- main
1010

1111
jobs:
1212
build-desktop-mac:
@@ -110,31 +110,35 @@ jobs:
110110
fetch-depth: 0
111111
- name: Check for manual edits to /docs
112112
run: |
113-
echo "${{ github.event.pull_request.head.sha }} -- ${{ github.event.pull_request.head.sha }}"
114-
# disable for now
115-
# bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }}
113+
echo "${{ github.event.pull_request.head.sha }} -- ${{ github.event.pull_request.head.sha }}"
114+
# disable for now
115+
# bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }}
116116
117117
test-renderdiff:
118118
name: test-renderdiff
119119
runs-on: macos-14-xlarge
120120
steps:
121+
- uses: actions/checkout@v4.1.6
122+
with:
123+
fetch-depth: 0
124+
- id: get_commit_msg
125+
uses: ./.github/actions/get-commit-msg
121126
- uses: actions/checkout@v4.1.6
122127
with:
123128
fetch-depth: 0
124129
- uses: ./.github/actions/mac-prereq
125130
- name: Cache Mesa and deps
126-
id: mesa-cache
127131
uses: actions/cache@v4
128132
with:
129133
path: mesa
130134
key: ${{ runner.os }}-mesa-deps-2-${{ vars.MESA_VERSION }}
131135
- name: Prerequisites
132-
id: prereqs
133136
run: |
134137
bash build/common/get-mesa.sh
135138
pip install tifffile numpy
136139
- name: Run Test
137-
run: bash test/renderdiff/test.sh
140+
run: |
141+
echo "${{ steps.get_commit_msg.outputs.msg }}" | bash test/renderdiff/test.sh
138142
- uses: actions/upload-artifact@v4
139143
with:
140144
name: presubmit-renderdiff-result

build/common/get-mesa.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ for cmd in "${NEEDED_PYTHON_DEPS[@]}"; do
4141
done
4242
deactivate
4343

44+
LOCAL_PKG_CONFIG_PATH=
45+
4446
# Install system deps
4547
if [[ "$OS_NAME" == "Linux" ]]; then
4648
if [[ "$GITHUB_WORKFLOW" ]]; then
@@ -82,6 +84,9 @@ elif [[ "$OS_NAME" == "Darwin" ]]; then
8284
fi
8385
fi
8486
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=true brew install autoconf automake libx11 libxext libxrandr llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
87+
88+
# For reasons unknown, this is necessary for pkg-config to find homebrew's packages
89+
LOCAL_PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"
8590
fi # [[ "$OS_NAME" == x ]]
8691

8792
LOCAL_LDFLAGS=${LDFLAGS}
@@ -134,9 +139,11 @@ fi
134139
# -Dgallium-drivers=swrast => builds GL software rasterizer
135140
# -Dvulkan-drivers=swrast => builds VK software rasterizer
136141
# -Dgallium-drivers=llvmpipe is needed for GL >= 4.1 pipe-screen (see src/gallium/auxiliary/target-helpers/inline_sw_helper.h)
137-
CXX=${LOCAL_CXX} CC=${LOCAL_CC} PATH=${LOCAL_PATH} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
142+
PKG_CONFIG_PATH=${LOCAL_PKG_CONFIG_PATH} PATH=${LOCAL_PATH} \
143+
CXX=${LOCAL_CXX} CC=${LOCAL_CC} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
138144
meson setup --wipe builddir/ -Dprefix="${MESA_DIR}/out" -Dglx=xlib -Dosmesa=true -Dgallium-drivers=llvmpipe,swrast -Dvulkan-drivers=swrast
139-
CXX=${LOCAL_CXX} CC=${LOCAL_CC} PATH=${LOCAL_PATH} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
145+
PKG_CONFIG_PATH=${LOCAL_PKG_CONFIG_PATH} PATH=${LOCAL_PATH} \
146+
CXX=${LOCAL_CXX} CC=${LOCAL_CC} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
140147
meson install -C builddir/
141148

142149
# Disable python venv

test/renderdiff/README.md

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,72 @@ machines. To perform software rasterization, these scripts are centered around [
77
rasterizers, but nothing bars us from using another rasterizer like [SwiftShader]. Additionally,
88
we should be able to use GPUs where available (though this is more of a future work).
99

10-
The script `run.py` contains the core logic for taking input parameters (such as the test
11-
description file) and then running gltf_viewer to produce the results.
10+
The script `render.py` contains the core logic for taking input parameters (such as the test
11+
description file) and then running gltf_viewer to produce the renderings.
1212

1313
In the `test` directory is a list of test descriptions that are specified in json. Please see
1414
`sample.json` to parse the structure.
1515

16+
## Running the test locally
17+
- To run the same presbumit as [`test-renderdiff`][presubmit-renderdiff], you can do
18+
```
19+
bash test/renderdiff/test.sh
20+
```
21+
- This script will generate the renderings based on the current state of your repo.
22+
Additionally, it will also compare the generated images with corresponding images in the
23+
golden repo.
24+
- To just render without running the test, you could use the following script
25+
```
26+
bash test/renderdiff/generate.sh
27+
```
28+
29+
## Update the golden images
30+
The golden images are stored in a github repository: https://github.com/google/filament-assets.
31+
Filament team members should have access to write to the repository. A typical flow for updating
32+
the goldens is to upload your changed images into **branch** of `filament-assets`. This branch is
33+
paired with a PR or commit on the `filament` repo.
34+
35+
As an example, imagine I am working on a PR, and I've uploaded my change, which is in a branch
36+
called `my-pr-branch`, to `filament`. This PR requires updating the golden. We would do it
37+
in the following fashion
38+
39+
### Using a script to update the golden repo
40+
41+
- Run interactive mode in the `update_golden.py` script.
42+
```
43+
python3 test/renderdiff/src/update_golden.py
44+
```
45+
- This will guide you through a series of steps to push the changes to a remote branch
46+
on `filament-assets`.
47+
48+
### Manually updating the golden repo
49+
50+
- Check out the golden repo
51+
```
52+
git clone git@github.com:google/filament-assets.git
53+
```
54+
- Create a branch on the golden repo
55+
```
56+
cd filament-assets
57+
git switch -c my-pr-branch-golden
58+
```
59+
- Copy the new images to their appropriate place in `filament-assets`
60+
- Push the `filament-assets` working branch to remote
61+
```
62+
git push origin my-pr-branch-golden
63+
```
64+
- In the commit message of your working branch on `filament`, add the following line
65+
```
66+
RDIFF_BBRANCH=my-pr-branch-golden
67+
```
68+
### Manually updating the golden repo
69+
70+
Doing the above has multiple effects:
71+
- The presubmit test [`test-renderdiff`][presubmit-renderdiff] will test against the provided
72+
branch of the golden repo (i.e. `my-pr-branch-golden`).
73+
- If the PR is merged, then there is another workflow that will merge `my-pr-branch-golden` to
74+
the `main` branch of the golden repo.
75+
1676
[Mesa]: https://docs.mesa3d.org
17-
[SwiftShader]: https://github.com/google/swiftshader
77+
[SwiftShader]: https://github.com/google/swiftshader
78+
[presubmit-renderdiff]: https://github.com/google/filament/blob/e85dfe75c86106a05019e13ccdbef67e030af675/.github/workflows/presubmit.yml#L118

test/renderdiff/src/workflow_presubmit_msg.py renamed to test/renderdiff/src/commit_msg.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from utils import execute
15+
import sys
16+
import re
1617

17-
def get_last_commit():
18-
res, o = execute('git log -1')
19-
commit, author, date, _, title, *desc = o.split('\n')
18+
from utils import execute, ArgParseImpl
19+
20+
RDIFF_UPDATE_GOLDEN_STR = 'RDIFF_BRANCH'
21+
22+
def _parse_commit(commit_str):
23+
commit, author, date, _, title, *desc = commit_str.split('\n')
2024
commit = commit.split(' ')[1]
2125
title = title.strip()
2226

@@ -30,28 +34,27 @@ def get_last_commit():
3034
desc
3135
)
3236

33-
def sanitized_split(line, split_atom='\n'):
34-
return list(
35-
filter(
36-
lambda x: len(x) > 0,
37-
map(
38-
lambda x: x.strip(),
39-
line.split(split_atom)
40-
)
41-
)
42-
)
37+
if __name__ == "__main__":
38+
RE_STR = rf"{RDIFF_UPDATE_GOLDEN_STR}(?:S)?=[\[]?([a-zA-Z0-9,\s\-\/]+)[\]]?"
4339

44-
RDIFF_UPDATE_GOLDEN_STR = 'RDIFF_UPDATE_GOLDEN'
40+
parser = ArgParseImpl()
41+
parser.add_argument('--file', help='A file containing the commit message')
42+
args, _ = parser.parse_known_args(sys.argv[1:])
4543

46-
if __name__ == "__main__":
47-
RE_STR = f'{RDIFF_UPDATE_GOLDEN_STR}(?:S)?=[\[]?([a-zA-Z0-9,\s]+)[\]]?'
44+
if not args.file:
45+
msg = sys.stdin.read()
46+
else:
47+
with open(args.file, 'r') as f:
48+
msg = f.read()
4849

4950
to_update = []
50-
commit, title, description = get_last_commit()
51+
commit, title, description = _parse_commit(msg)
5152
for line in description:
5253
m = re.match(RE_STR, line)
5354
if not m:
5455
continue
56+
print(m.group(1))
57+
exit(0)
5558

56-
to_update += sanitize_split(m.group(1).replace(',', ' '), ' ')
57-
print(','.join(to_update))
59+
# Always default to the main branch
60+
print('main')

test/renderdiff/src/golden_manager.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def _prepare(self):
6565
assets_dir = self._assets_dir()
6666
if not os.path.exists(assets_dir):
6767
execute(
68-
f'git clone --depth=1 {self._get_repo_url()}',
68+
f'git clone {self._get_repo_url()}',
6969
cwd=self.working_dir_,
7070
capture_output=False
7171
)
@@ -83,13 +83,26 @@ def update(self):
8383
self._git_exec('rebase')
8484

8585
def _git_exec(self, cmd):
86-
execute(f'git {cmd}', cwd=self._assets_dir(), capture_output=False)
86+
return execute(f'git {cmd}', cwd=self._assets_dir(), capture_output=False)
8787

88-
def merge_to_main(self, branch, push_to_remote=False):
88+
# tag represent a hash in the filament repo that this merge is associated with
89+
def merge_to_main(self, branch, tag, push_to_remote=False):
8990
self.update()
9091
assets_dir = self._assets_dir()
92+
93+
# Update commit message
94+
self._git_exec(f'checkout {branch}')
95+
code, old_commit = execute(f'git log --format=%B -n 1', cwd=assets_dir)
96+
if tag and len(tag) > 0:
97+
old_commit += f'\nFILAMENT={tag}'
98+
COMMIT_FILE = '/tmp/golden_commit.txt'
99+
with open(COMMIT_FILE, 'w') as f:
100+
f.write(old_commit)
101+
self._git_exec(f'commit --amend -F {COMMIT_FILE}')
102+
103+
# Do the actual merge
91104
self._git_exec(f'checkout main')
92-
self._git_exec(f'merge --no-ff {branch}')
105+
self._git_exec(f'merge --no-ff --no-edit {branch}')
93106
if push_to_remote and \
94107
(self.access_token_ or self.access_type_ == ACCESS_TYPE_SSH):
95108
self._git_exec(f'push origin main')
@@ -109,7 +122,7 @@ def source_from(self, src_dir, commit_msg, branch,
109122
self._git_exec(f'add {GOLDENS_DIR}')
110123
else:
111124
for f in deletes:
112-
self._git_exec(f'remove {os.path.join(GOLDENS_DIR, f)}')
125+
self._git_exec(f'rm {os.path.join(GOLDENS_DIR, f)}')
113126
for f in updates:
114127
shutil.copy2(
115128
os.path.join(src_dir, f),

0 commit comments

Comments
 (0)