Skip to content

Commit 6b3479c

Browse files
Merge branch 'main' into dev/sashwinbalaji/re2_tp
2 parents 0614a98 + f25be28 commit 6b3479c

21 files changed

Lines changed: 666 additions & 49 deletions

File tree

.github/workflows/cut-canary.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright (C) 2026 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Cuts canary by creating a merge commit on `canary` whose tree equals
16+
# the current tip of `main`. Manual trigger via the GitHub Actions UI.
17+
#
18+
# Uses the same tree-replacing merge pattern as merge-main-to-canary.yml
19+
# (git merge -s ours + git read-tree) so it always moves forward (no
20+
# force-push), preserves history on both sides, and handles the case of
21+
# cherry-picks on canary that have different SHAs than their
22+
# counterparts on main. Convention: every fix goes to main first and is
23+
# then cherry-picked to canary; anything canary-only would otherwise be
24+
# silently dropped by this operation.
25+
#
26+
# Pushes to canary subsequently trigger UI Cloud Build to redeploy the
27+
# canary channel. See RFC-0022.
28+
29+
name: Cut canary
30+
31+
on:
32+
workflow_dispatch:
33+
34+
permissions:
35+
contents: write # Required to push canary
36+
37+
jobs:
38+
cut-canary:
39+
runs-on: ubuntu-latest
40+
environment: canary
41+
steps:
42+
- name: Checkout canary
43+
uses: actions/checkout@v4
44+
with:
45+
ref: canary
46+
fetch-depth: 0
47+
48+
- name: Fetch main
49+
run: git fetch origin main
50+
51+
- name: Short-circuit if canary already matches main
52+
run: |
53+
if [[ "$(git rev-parse HEAD^{tree})" == \
54+
"$(git rev-parse origin/main^{tree})" ]]; then
55+
echo "::notice::canary tree already matches main; nothing to do."
56+
echo "SKIP=1" >> "$GITHUB_ENV"
57+
fi
58+
59+
- name: Configure git
60+
if: env.SKIP != '1'
61+
run: |
62+
git config user.name "github-actions[bot]"
63+
git config user.email "github-actions[bot]@users.noreply.github.com"
64+
65+
- name: Merge main into canary (replace tree with main)
66+
if: env.SKIP != '1'
67+
run: |
68+
git merge -s ours origin/main --no-commit
69+
git read-tree -m -u origin/main
70+
git commit -m "Cut canary from main (automated)"
71+
72+
- name: Push canary
73+
if: env.SKIP != '1'
74+
run: |
75+
git push origin HEAD:canary
76+
echo "::notice::canary updated to tree of $(git rev-parse origin/main)."
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright (C) 2026 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Creates a draft GitHub Release on vX.Y tag push.
16+
#
17+
# The body is pre-populated with the matching CHANGELOG section as a
18+
# starting point. A maintainer is expected to edit it into full prose
19+
# release notes before clicking `finalize-release` to publish.
20+
#
21+
# Idempotent: re-running on an existing tag re-creates the draft only if
22+
# one does not exist; it never clobbers a release that has already been
23+
# published or edited.
24+
25+
name: Draft release
26+
27+
on:
28+
push:
29+
tags:
30+
- 'v[0-9]+.[0-9]+'
31+
32+
permissions:
33+
contents: write # Required to create the release
34+
35+
jobs:
36+
draft:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@v4
41+
with:
42+
ref: ${{ github.ref }}
43+
44+
- name: Extract CHANGELOG section for this tag
45+
run: |
46+
python3 tools/release/extract_changelog_section.py \
47+
"${{ github.ref_name }}" > /tmp/release_body.txt
48+
echo "--- Draft release body ---"
49+
cat /tmp/release_body.txt
50+
51+
- name: Create draft release (if missing)
52+
env:
53+
GH_TOKEN: ${{ github.token }}
54+
run: |
55+
TAG="${{ github.ref_name }}"
56+
if gh release view "$TAG" > /dev/null 2>&1; then
57+
echo "Release $TAG already exists — leaving body untouched."
58+
else
59+
gh release create "$TAG" \
60+
--draft \
61+
--title "Perfetto $TAG" \
62+
--notes-file /tmp/release_body.txt
63+
fi
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright (C) 2026 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Attaches LUCI-built binaries and SDK source zips to the matching draft
16+
# GitHub release. Leaves the release as a draft — a human publishes it
17+
# manually from the GitHub UI after reviewing the release notes.
18+
#
19+
# Manual trigger after LUCI completes. Idempotent — safe to re-run if a
20+
# previous invocation failed partway. See RFC-0022 "LUCI -> GitHub bridge".
21+
22+
name: Attach release artifacts
23+
24+
on:
25+
workflow_dispatch:
26+
inputs:
27+
version:
28+
description: 'Release version to finalize (e.g. v54.0)'
29+
required: true
30+
type: string
31+
32+
permissions:
33+
contents: write # Required to upload assets and publish the release
34+
35+
jobs:
36+
finalize:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Validate input
40+
env:
41+
VERSION: ${{ inputs.version }}
42+
run: |
43+
if ! [[ "$VERSION" =~ ^v[0-9]+\.[0-9]+$ ]]; then
44+
echo "::error::Version must match vX.Y (got: $VERSION)"
45+
exit 1
46+
fi
47+
48+
- name: Checkout tag
49+
uses: actions/checkout@v4
50+
with:
51+
ref: ${{ inputs.version }}
52+
fetch-depth: 0
53+
fetch-tags: true
54+
55+
- name: Verify draft release exists
56+
env:
57+
GH_TOKEN: ${{ github.token }}
58+
VERSION: ${{ inputs.version }}
59+
run: |
60+
if ! gh release view "$VERSION" --repo "${{ github.repository }}" \
61+
> /dev/null 2>&1; then
62+
echo "::error::No release found for tag $VERSION. Push the tag \
63+
first (via promote-stable.yml) to create the draft."
64+
exit 1
65+
fi
66+
67+
- name: Install gcloud / gsutil
68+
uses: google-github-actions/setup-gcloud@v2
69+
70+
- name: Download, verify, and package LUCI artifacts
71+
env:
72+
VERSION: ${{ inputs.version }}
73+
run: |
74+
tools/release/package-github-release-artifacts --yes "$VERSION"
75+
76+
- name: Upload assets to draft release
77+
env:
78+
GH_TOKEN: ${{ github.token }}
79+
VERSION: ${{ inputs.version }}
80+
run: |
81+
STAGING="/tmp/perfetto-${VERSION}-github-release"
82+
gh release upload "$VERSION" "$STAGING"/*.zip \
83+
--repo "${{ github.repository }}" --clobber
84+
echo "::notice::Artifacts attached. Review the draft release at \
85+
https://github.com/${{ github.repository }}/releases and publish it \
86+
manually when ready."
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Copyright (C) 2026 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Promotes canary to stable and tags the release.
16+
#
17+
# Creates a merge commit on `stable` whose tree equals the current tip of
18+
# `canary` (same tree-replacing merge pattern as cut-canary.yml), reads
19+
# the target version from the top of CHANGELOG (which must already have
20+
# been updated from 'Unreleased:' to 'vX.Y - YYYY-MM-DD:' before running),
21+
# then creates and pushes the vX.Y git tag at the new stable HEAD.
22+
#
23+
# The tag push is the single event that fans out to LUCI, Cloud Build,
24+
# and draft-release.yml. See RFC-0022.
25+
26+
name: Promote canary to stable
27+
28+
on:
29+
workflow_dispatch:
30+
31+
permissions:
32+
contents: write # Required to push stable and the tag
33+
34+
jobs:
35+
promote-stable:
36+
runs-on: ubuntu-latest
37+
environment: stable
38+
steps:
39+
- name: Checkout stable
40+
uses: actions/checkout@v4
41+
with:
42+
ref: stable
43+
fetch-depth: 0
44+
45+
- name: Fetch canary
46+
run: git fetch origin canary
47+
48+
- name: Short-circuit if stable already matches canary
49+
run: |
50+
if [[ "$(git rev-parse HEAD^{tree})" == \
51+
"$(git rev-parse origin/canary^{tree})" ]]; then
52+
echo "::error::stable tree already matches canary; nothing to \
53+
promote. Cut canary first."
54+
exit 1
55+
fi
56+
57+
- name: Extract version from CHANGELOG
58+
id: version
59+
run: |
60+
# First non-whitespace line must be a released version header.
61+
# Anything else (e.g. still 'Unreleased:') means the release
62+
# hasn't been marked ready. Update CHANGELOG on main, re-cut
63+
# canary, and retry.
64+
FIRST=$(git show "origin/canary:CHANGELOG" \
65+
| grep -m1 -E '^[^[:space:]]' || true)
66+
if ! [[ "$FIRST" =~ ^(v[0-9]+\.[0-9]+)[[:space:]]+-[[:space:]]+[0-9]{4}-[0-9]{2}-[0-9]{2}: ]]; then
67+
echo "::error::CHANGELOG top entry is not a released version \
68+
header (got: '$FIRST'). Update CHANGELOG to 'vX.Y - YYYY-MM-DD:' on main, \
69+
re-cut canary, and retry."
70+
exit 1
71+
fi
72+
VERSION="${BASH_REMATCH[1]}"
73+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
74+
echo "::notice::Promoting as $VERSION"
75+
76+
- name: Verify tag does not already exist
77+
run: |
78+
VERSION="${{ steps.version.outputs.version }}"
79+
if git rev-parse "refs/tags/$VERSION" >/dev/null 2>&1; then
80+
echo "::error::Tag $VERSION already exists. Bump CHANGELOG to \
81+
the next version on main and re-cut canary."
82+
exit 1
83+
fi
84+
85+
- name: Configure git
86+
run: |
87+
git config user.name "github-actions[bot]"
88+
git config user.email "github-actions[bot]@users.noreply.github.com"
89+
90+
- name: Merge canary into stable (replace tree with canary)
91+
run: |
92+
git merge -s ours origin/canary --no-commit
93+
git read-tree -m -u origin/canary
94+
git commit -m "Promote canary to stable (${{ steps.version.outputs.version }}, automated)"
95+
96+
- name: Push stable
97+
run: |
98+
git push origin HEAD:stable
99+
100+
- name: Create and push tag
101+
run: |
102+
VERSION="${{ steps.version.outputs.version }}"
103+
git tag -a "$VERSION" HEAD -m "Perfetto $VERSION"
104+
git push origin "refs/tags/$VERSION"
105+
echo "::notice::Tagged $VERSION at $(git rev-parse HEAD). \
106+
LUCI, Cloud Build, and draft-release.yml have been triggered."

gn/standalone/hash_file.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env python3
2+
# Copyright (C) 2026 The Android Open Source Project
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Prints a short hex digest of the given file. Used from GN to fold a file's
17+
# contents into a compile flag, so that ccache (which doesn't follow files
18+
# referenced by flags like -fsanitize-ignorelist=) invalidates when the file
19+
# changes.
20+
21+
import hashlib
22+
import sys
23+
24+
25+
def main():
26+
with open(sys.argv[1], 'rb') as f:
27+
print(hashlib.sha256(f.read()).hexdigest()[:16])
28+
29+
30+
if __name__ == '__main__':
31+
sys.exit(main())

gn/standalone/sanitizers/BUILD.gn

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,20 @@ copy("ignorelist_copy") {
4343
config("sanitizers_cflags") {
4444
if (using_sanitizer) {
4545
ignorelist_path_ = rebase_path("ignorelist.txt", root_build_dir)
46+
47+
# -fsanitize-ignorelist only exposes the *path* on the command line, so
48+
# ccache (which hashes arguments and source files but not files referenced
49+
# by arguments) happily serves stale objects when the ignorelist contents
50+
# change. Fold a content hash of the ignorelist into a -D define so any
51+
# edit to it alters the compile command and invalidates the cache.
52+
ignorelist_hash_ = exec_script("//gn/standalone/hash_file.py",
53+
[ rebase_path("ignorelist.txt") ],
54+
"trim string")
4655
cflags = [
4756
"-fno-omit-frame-pointer",
4857
"-fsanitize-ignorelist=$ignorelist_path_",
4958
]
50-
defines = []
59+
defines = [ "PERFETTO_SANITIZERS_IGNORELIST_HASH=\"$ignorelist_hash_\"" ]
5160

5261
if (is_asan) {
5362
cflags += [ "-fsanitize=address" ]

0 commit comments

Comments
 (0)