Skip to content

Commit 81e1951

Browse files
committed
Added automated nightly builds.
1 parent c4f2ef1 commit 81e1951

File tree

5 files changed

+595
-28
lines changed

5 files changed

+595
-28
lines changed

.github/workflows/image.yml

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
name: image
2+
on:
3+
workflow_dispatch:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
contents: read
9+
packages: write
10+
attestations: write
11+
id-token: write
12+
13+
defaults:
14+
run:
15+
shell: bash
16+
17+
concurrency:
18+
group: "image"
19+
cancel-in-progress: true
20+
21+
env:
22+
REGISTRY: ghcr.io
23+
REGISTRY_IMAGE: ghcr.io/borrowsanitizer/rust
24+
COMPRESSION: .tar.xz
25+
26+
jobs:
27+
release-info:
28+
# Every time we publish a new release, we want to build a corresponding
29+
# Docker image. However, we also want to be able to manually trigger this workflow
30+
# for debugging purposes. For this reason, instead of relying on the properties of `github.event`,
31+
# we query the GitHub API manually.
32+
name: Gather release info
33+
outputs:
34+
repo: ${{ steps.release-info.outputs.repo }}
35+
sha: ${{ steps.release-info.outputs.sha }}
36+
tag: ${{ steps.release-info.outputs.tag }}
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Gather release info
40+
id: release-info
41+
env:
42+
GH_TOKEN: ${{ github.token }}
43+
run: |
44+
RELEASE_TAG=$(gh api repos/${{ github.repository }}/releases --jq 'sort_by(.created_at) | reverse | .[0].tag_name')
45+
RELEASE_SHA=$(gh api repos/${{ github.repository }}/git/refs/tags/$RELEASE_TAG --jq '.object.sha')
46+
echo "repo=${GITHUB_REPOSITORY@L}" >> $GITHUB_OUTPUT
47+
sha=$(echo "$RELEASE_SHA" | cut -c1-7)
48+
echo "tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
49+
echo "sha=$sha" >> $GITHUB_OUTPUT
50+
51+
# Builds a series of Docker images; one for each supported architecture
52+
# Each image has a corresponding "digest" that's saved as an artifact.
53+
# Each digest is combined into a single, multi-architecture image in the final stage.
54+
build:
55+
needs: release-info
56+
runs-on: ubuntu-latest
57+
strategy:
58+
fail-fast: false
59+
matrix:
60+
config:
61+
- platform: linux/amd64
62+
target: x86_64-unknown-linux-gnu
63+
steps:
64+
- name: Checkout
65+
uses: actions/checkout@v4
66+
- name: Prepare
67+
run: |
68+
platform=${{ matrix.config.platform }}
69+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
70+
71+
- name: Docker meta
72+
id: meta
73+
uses: docker/metadata-action@v5
74+
with:
75+
images: ${{ env.REGISTRY_IMAGE }}
76+
77+
# Our releases artifacts will always be a series of compressed archives
78+
# with names matching each supported target. For example, when we're building
79+
# an image for `x86_64-unknown-linux-gnu`, we want `x86_64-unknown-linux-gnu.tar.xz`.
80+
- name: Resolve URLs
81+
id: resolve_urls
82+
env:
83+
GH_TOKEN: ${{ github.token }}
84+
run: |
85+
QUERY=".assets[] | select(.url | endswith(\"${{matrix.config.target}}${{ env.COMPRESSION }}\")) | \"\(.url)\""
86+
url=$(gh release view ${{ needs.release-info.outputs.tag }} --repo ${{ github.repository }} --json assets -q "$QUERY")
87+
if [ ! "$url" ]; then
88+
echo "Unable to resolve url for release asset."
89+
exit 1
90+
fi
91+
echo "url_basename=$(basename $url ${{ env.COMPRESSION }})" >> "$GITHUB_OUTPUT"
92+
echo "url=$url" >> "$GITHUB_OUTPUT"
93+
94+
- name: Login
95+
uses: docker/login-action@v3
96+
with:
97+
registry: ${{ env.REGISTRY }}
98+
username: ${{ github.actor }}
99+
password: ${{ secrets.GITHUB_TOKEN }}
100+
101+
- name: Set up QEMU
102+
uses: docker/setup-qemu-action@v3
103+
104+
- name: Set up Docker Buildx
105+
uses: docker/setup-buildx-action@v3
106+
107+
- name: Build and push by digest
108+
id: build
109+
uses: docker/build-push-action@v6
110+
with:
111+
context: .
112+
file: ./src/ci/bsan/Dockerfile.bsan
113+
platforms: ${{ matrix.config.platform }}
114+
labels: ${{ steps.meta.outputs.labels }}
115+
tags: ${{ env.REGISTRY_IMAGE }}
116+
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
117+
# URL - The URL of the compressed toolchain, which is downloaded, extracted, and installed when building the image.
118+
# TARGET - The current target; e.g. `aarch64-apple-darwin`.
119+
# PREFIX - A string placed before the name of the target for the toolchain installed within the container.
120+
# For example, "$PREFIX-$TARGET" will be listed as the only toolchain installed.
121+
build-args: |
122+
URL=${{ steps.resolve_urls.outputs.url }}
123+
TARGET=${{ matrix.config.target }}
124+
PREFIX=bsan-${{ needs.release-info.outputs.tag }}-${{needs.release-info.outputs.sha}}
125+
126+
- name: Export digest
127+
run: |
128+
mkdir -p ${{ runner.temp }}/digests
129+
digest="${{ steps.build.outputs.digest }}"
130+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
131+
132+
- name: Upload digest
133+
uses: actions/upload-artifact@v4
134+
with:
135+
name: digests-${{ env.PLATFORM_PAIR }}
136+
path: ${{ runner.temp }}/digests/*
137+
if-no-files-found: error
138+
retention-days: 1
139+
140+
merge:
141+
runs-on: ubuntu-latest
142+
needs: [release-info, build]
143+
steps:
144+
- name: Download digests
145+
uses: actions/download-artifact@v4
146+
with:
147+
path: ${{ runner.temp }}/digests
148+
pattern: digests-*
149+
merge-multiple: true
150+
151+
- name: Login
152+
uses: docker/login-action@v3
153+
with:
154+
registry: ${{ env.REGISTRY }}
155+
username: ${{ github.actor }}
156+
password: ${{ secrets.GITHUB_TOKEN }}
157+
158+
- name: Set up Docker Buildx
159+
uses: docker/setup-buildx-action@v3
160+
161+
- name: Docker meta
162+
id: meta
163+
uses: docker/metadata-action@v5
164+
with:
165+
images: ${{ env.REGISTRY_IMAGE }}
166+
tags: |
167+
type=raw,value=${{ needs.release-info.outputs.tag }}
168+
- name: Create manifest list and push
169+
working-directory: ${{ runner.temp }}/digests
170+
run: |
171+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
172+
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
173+
174+
- name: Inspect image
175+
run: |
176+
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
177+
178+
cleanup:
179+
runs-on: ubuntu-latest
180+
needs: [merge]
181+
steps:
182+
- name: Delete untagged images
183+
env:
184+
GH_TOKEN: ${{ github.token }}
185+
run: |
186+
ENDPOINT=/orgs/${{ github.repository_owner }}/packages/container/rust/versions
187+
gh api "$ENDPOINT" --paginate \
188+
-q '.[] | select(.metadata.container.tags | length == 0) | .id' |
189+
while read -r id; do
190+
gh api -X DELETE "$ENDPOINT/$id"
191+
done
192+

.github/workflows/release.yml

Lines changed: 113 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: release
22
on:
33
schedule:
4-
- cron: "0 0 * * 1"
4+
- cron: "5 0 * * *"
55
workflow_dispatch:
66
permissions:
77
contents: write
@@ -11,29 +11,45 @@ defaults:
1111
concurrency:
1212
group: "release"
1313
cancel-in-progress: true
14+
env:
15+
prefix: bsan
16+
1417
jobs:
1518
init:
1619
runs-on: ubuntu-latest
1720
name: Init
1821
outputs:
1922
should_run: ${{ steps.should_run.outputs.should_run }}
23+
rustc_sha: ${{ steps.info.outputs.RUSTC_SHA }}
24+
rustc_version: ${{ steps.info.outputs.RUSTC_VERSION }}
25+
release_name: ${{ steps.info.outputs.RELEASE_NAME }}
26+
2027
steps:
2128
- uses: actions/checkout@v4
2229
with:
30+
repository: BorrowSanitizer/rust
2331
fetch-depth: 0
32+
2433
- name: Set version info
34+
id: info
2535
run: |
36+
export RUSTC_VERSION=$(cat src/version)
2637
export DATE=$(git log -1 --format=%cd --date=format:%Y-%m-%d)
27-
export TAG_NAME=$(echo ${{ github.sha }} | cut -c1-7)
28-
export RELEASE_NAME="$DATE-$TAG_NAME"
38+
export RUSTC_SHA=$(git rev-parse HEAD)
39+
export RELEASE_NAME="$DATE-$(echo $RUSTC_SHA | cut -c1-7)"
40+
echo "RELEASE_NAME=$RELEASE_NAME" >> "$GITHUB_OUTPUT"
41+
echo "RUSTC_VERSION=$RUSTC_VERSION" >> "$GITHUB_OUTPUT"
42+
echo "RUSTC_SHA=$RUSTC_SHA" >> "$GITHUB_OUTPUT"
43+
echo "$RUSTC_VERSION"
44+
echo "$RUSTC_SHA"
2945
echo "$RELEASE_NAME"
30-
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
31-
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV
32-
- id: should_run
46+
47+
- name: Check if updates have been published
48+
id: should_run
3349
continue-on-error: true
34-
name: Check if updates have been published
3550
if: ${{ github.event_name == 'schedule' }}
3651
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"
52+
3753
build:
3854
needs: [init]
3955
strategy:
@@ -42,41 +58,112 @@ jobs:
4258
config:
4359
- os: ubuntu-latest
4460
target: x86_64-unknown-linux-gnu
61+
free_disk: true
4562
- os: macos-latest
4663
target: aarch64-apple-darwin
64+
free_disk: false
4765
runs-on: '${{ matrix.config.os }}'
4866
name: 'Build (${{ matrix.config.target }})'
4967
steps:
68+
5069
- uses: actions/checkout@v4
5170
with:
71+
repository: BorrowSanitizer/rust
5272
fetch-depth: 0
53-
- name: Install dependencies
73+
74+
- name: Configure
75+
id: config
76+
continue-on-error: true
5477
run: |
55-
rustup component add llvm-tools-preview
56-
cp src/bootstrap/defaults/config.bsan.dev.toml config.toml
57-
- name: Upstream
58-
run: src/ci/scripts/setup-upstream-remote.sh
78+
git config --global --add safe.directory $GITHUB_WORKSPACE
79+
src/ci/scripts/setup-upstream-remote.sh
80+
echo "artifact=${{ env.prefix }}-${{ needs.init.outputs.release_name }}-${{ matrix.config.target }}" >> $GITHUB_OUTPUT
81+
82+
- name: Install dependencies
83+
run: rustup component add llvm-tools-preview
84+
85+
- name: Free up disk space
86+
run: src/ci/scripts/free-disk-space.sh
87+
if: matrix.config.free_disk
88+
5989
- name: Dist
60-
run: ./x.py dist --config src/bootstrap/defaults/config.dist.toml
90+
run: ./x.py dist --config src/bootstrap/defaults/config.bsan.release.toml
91+
92+
- name: Rename to target
93+
run: |
94+
mv ./build/dist/rust-${{ needs.init.outputs.rustc_version }}-dev-${{ matrix.config.target }}.tar.xz \
95+
./${{ steps.config.outputs.artifact }}.tar.xz
96+
6197
- name: Publish
6298
uses: actions/upload-artifact@v4
6399
with:
64-
name: bsan-${{ matrix.config.os }}-${{ matrix.config.arch }}
65-
path: build/dist/rust-nightly-${{ matrix.config.target }}.tar.xz
100+
compression-level: 0
101+
name: ${{ steps.config.outputs.artifact }}
102+
path: ./${{ steps.config.outputs.artifact }}.tar.xz
103+
66104
release:
67105
name: Update rolling release
68106
needs: [init, build]
69107
runs-on: macos-latest
70108
steps:
71-
- name: Download artifact
109+
- name: Download all artifacts
110+
id: artifact_download
72111
uses: actions/download-artifact@v4
73-
with:
74-
merge-multiple: true
75-
path: artifacts
76-
- name: Release
77-
uses: softprops/action-gh-release@v2
78-
with:
79-
tag_name: rolling
80-
prerelease: true
81-
files: |
82-
artifacts/*.tar.xz
112+
113+
- name: Unzip doubly-compressed artifacts
114+
run: |
115+
find . -name "*.zip" -exec unzip -o -d . {} \;
116+
find . -name "*.tar.xz"
117+
118+
- name: Delete current rolling release tag
119+
continue-on-error: true
120+
env:
121+
GH_TOKEN: ${{ github.token }}
122+
run: gh api -X DELETE "/repos/BorrowSanitizer/rust/git/refs/tags/rolling"
123+
124+
- name: Prepare draft release
125+
env:
126+
GH_TOKEN: ${{ github.token }}
127+
run: |
128+
gh api \
129+
-X PATCH \
130+
/repos/BorrowSanitizer/rust/releases/${{ vars.RELEASE_ID }} \
131+
-f "tag_name=rolling" \
132+
-f "target_commitish=${{ needs.init.outputs.rustc_sha }}" \
133+
-f "name=Rolling Release ${{ needs.init.outputs.release_name }}" \
134+
-f "body=Rolling release from continuous integration." \
135+
-F "draft=true" \
136+
-F "prerelease=true"
137+
138+
- name: Delete all existing assets
139+
env:
140+
GH_TOKEN: ${{ github.token }}
141+
run: |
142+
for ASSET in $(gh api /repos/BorrowSanitizer/rust/releases/${{ vars.RELEASE_ID }}/assets -q '.[].id'); do
143+
echo "Deleting asset $ASSET"
144+
gh api -X DELETE "/repos/BorrowSanitizer/rust/releases/assets/$ASSET"
145+
done
146+
147+
- name: Upload distribution files
148+
env:
149+
GH_TOKEN: ${{ github.token }}
150+
run: |
151+
gh release upload \
152+
rolling \
153+
$(find . -name "*.tar.xz") \
154+
--repo BorrowSanitizer/rust
155+
156+
- name: Publish release
157+
env:
158+
GH_TOKEN: ${{ github.token }}
159+
run: |
160+
gh api \
161+
-X PATCH \
162+
"/repos/BorrowSanitizer/rust/releases/${{ vars.RELEASE_ID }}" \
163+
-F "draft=false"
164+
165+
- name: Trigger image workflow
166+
env:
167+
GH_TOKEN: ${{ github.token }}
168+
run: |
169+
gh workflow run image

0 commit comments

Comments
 (0)