Skip to content

Commit 2c9ab37

Browse files
committed
Merge branch 'main' into main
2 parents df0e902 + 774c2b6 commit 2c9ab37

File tree

24 files changed

+935
-54
lines changed

24 files changed

+935
-54
lines changed
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# A GitHub action that loads rust tools and toolchains from cache. If there is a miss, it will install
2+
# them. the tools are read from the tools section of the rust-toolchain.toml file at the root of the repository.
3+
#
4+
# Copyright (c) Microsoft Corporation.
5+
# SPDX-License-Identifier: BSD-2-Clause-Patent
6+
#
7+
8+
name: "Install Rust Tools"
9+
description: "This action loads rust tools and toolchains from cache, or installs them."
10+
11+
runs:
12+
using: composite
13+
steps:
14+
- name: Rust Tool Cache
15+
id: tool-cache
16+
uses: actions/cache@v4
17+
with:
18+
path: |
19+
~/.cargo/bin/
20+
~/.rustup/toolchains/
21+
key: ${{ runner.os }}-rust-tools-${{ hashFiles('**/rust-toolchain.toml' )}}
22+
23+
- name: Install cargo-binstall
24+
uses: cargo-bins/[email protected]
25+
26+
# Read any tools from rust-toolchain.toml file and installs them
27+
- name: Install Rust Tools
28+
shell: bash
29+
run: |
30+
FILE="rust-toolchain.toml"
31+
32+
if [ ! -f "$FILE" ]; then
33+
echo "::error::File $FILE not found."
34+
exit 1
35+
fi
36+
37+
if ! grep -q '^\[tools\]' "$FILE"; then
38+
echo "::warning::[tools] section not found in $FILE."
39+
exit 1
40+
fi
41+
42+
# Extract tools section from rust-toolchain.toml
43+
sed -n '/\[tools\]/,/^$/p' "$FILE" | grep -v '\[tools\]' | while read -r line; do
44+
# Extract tool name and clean it
45+
TOOL_NAME=${line%%=*}
46+
TOOL_NAME=${TOOL_NAME//[[:space:]]/}
47+
TOOL_NAME="${TOOL_NAME//$'\n'/}"
48+
49+
# Extract tool version and clean it
50+
TOOL_VERSION=${line#*=}
51+
TOOL_VERSION=${TOOL_VERSION//[[:space:]]/}
52+
TOOL_VERSION=${TOOL_VERSION//\"/}
53+
TOOL_VERSION="${TOOL_VERSION//$'\n'/}"
54+
55+
echo ""
56+
echo "##################################################################"
57+
echo "Installing $TOOL_NAME@$TOOL_VERSION"
58+
echo "##################################################################"
59+
echo ""
60+
61+
# Attempt to binstall the tool first. If it fails, install it using cargo
62+
cargo binstall -y $TOOL_NAME --version $TOOL_VERSION || cargo install $TOOL_NAME --version $TOOL_VERSION
63+
done
64+
if: steps.tool-cache.outputs.cache-hit != 'true'

.github/workflows/Build-Containers.yml

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ jobs:
3535
fail-fast: false
3636
matrix:
3737
include:
38+
- image_name: "Ubuntu-24"
39+
sub_images: "dev test build"
3840
- image_name: "Ubuntu-22"
3941
sub_images: "dev test build"
4042
env:

.github/workflows/ReleaseDrafter.yml

+118-14
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
#
1212
# 1. A "latest release branch"
1313
# - Example: `release/202405`
14-
# - Config file: `release-draft-config-n.yml`
14+
# - Config file: `release-draft-config-n.yml` and `release-draft-config-n-dev.yml`
1515
# 2. A "previous release branch"
1616
# - Example: `release/202311`
17-
# - Config file: `release-draft-config-n-1.yml`
17+
# - Config file: `release-draft-config-n-1.yml` and `release-draft-config-n-1-dev.yml`
1818
# 3. A "main branch"
1919
# - Example: `main`
2020
# - Config file: `release-draft-config.yml`
@@ -68,33 +68,137 @@ jobs:
6868
run: |
6969
fileContent=$(cat "${FILE_PATH}")
7070
latestMuReleaseBranch=$(echo "$fileContent" | grep -oP '(?<=latest_mu_release_branch = ").*(?=")')
71+
latestMuDevBranch=$(echo "$latestMuReleaseBranch" | sed 's/release/dev/')
7172
previousMuReleaseBranch=$(echo "$fileContent" | grep -oP '(?<=previous_mu_release_branch = ").*(?=")')
72-
echo "latest_mu_branch=${latestMuReleaseBranch}" >> $GITHUB_ENV
73-
echo "latest_mu_branch_full=refs/heads/${latestMuReleaseBranch}" >> $GITHUB_ENV
74-
echo "previous_mu_branch=${previousMuReleaseBranch}" >> $GITHUB_ENV
75-
echo "previous_mu_branch_full=refs/heads/${previousMuReleaseBranch}" >> $GITHUB_ENV
76-
- name: Build a ${{ env.latest_mu_branch }} Draft
77-
if: ${{ startsWith(github.ref, env.latest_mu_branch_full) }}
73+
previousMuDevBranch=$(echo "$previousMuReleaseBranch" | sed 's/release/dev/')
74+
echo "latest_mu_release_branch=${latestMuReleaseBranch}" >> $GITHUB_ENV
75+
echo "latest_mu_dev_branch=${latestMuDevBranch}" >> $GITHUB_ENV
76+
echo "latest_mu_dev_branch_full=refs/heads/${latestMuDevBranch}" >> $GITHUB_ENV
77+
echo "latest_mu_release_branch_full=refs/heads/${latestMuReleaseBranch}" >> $GITHUB_ENV
78+
echo "previous_mu_release_branch=${previousMuReleaseBranch}" >> $GITHUB_ENV
79+
echo "previous_mu_dev_branch=${previousMuDevBranch}" >> $GITHUB_ENV
80+
echo "previous_mu_dev_branch_full=refs/heads/${previousMuDevBranch}" >> $GITHUB_ENV
81+
echo "previous_mu_release_branch_full=refs/heads/${previousMuReleaseBranch}" >> $GITHUB_ENV
82+
- name: Build a ${{ env.latest_mu_release_branch }} Draft
83+
if: ${{ startsWith(github.ref, env.latest_mu_dev_branch_full) }}
7884
id: update_draft_n
79-
uses: release-drafter/release-drafter@v6.0.0
85+
uses: release-drafter/release-drafter@v6.1.0
8086
with:
8187
# Note: Path is relative to .github/
8288
config-name: release-draft-config-n.yml
8389
env:
8490
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
85-
- name: Build a ${{ env.previous_mu_branch }} Draft
86-
if: ${{ startsWith(github.ref, env.previous_mu_branch_full) }}
91+
- name: Draft Release for Current (${{ env.latest_mu_release_branch }}) Release Branch
92+
if: steps.update_draft_n.outcome == 'success'
93+
run: |
94+
# Prepare the release body
95+
release_body_path="${{ runner.temp }}/release_body.txt"
96+
release_body=$(cat <<'EOF'
97+
${{ steps.update_draft_n.outputs.body }}
98+
EOF
99+
)
100+
release_body="${release_body//\`/\\\`}"
101+
echo "${release_body}" > $release_body_path
102+
sed -i 's/\\`/`/g' $release_body_path
103+
sed -i '/\**Full Changelog\**:/d' $release_body_path
104+
105+
# Get the new tag and title
106+
new_tag=$(echo "${{ steps.update_draft_n.outputs.tag_name }}" | sed 's/dev-//')
107+
new_title=$(echo "${{ steps.update_draft_n.outputs.tag_name }}" | sed 's/dev/release/')
108+
109+
# Determine the corresponding tag names
110+
existing_tag_prefix=""
111+
tag_regex="v([0-9]{6}).*\."
112+
if [[ $new_tag =~ $tag_regex ]]; then
113+
existing_tag_prefix="${BASH_REMATCH[1]}"
114+
fi
115+
116+
# Delete the template dev draft created
117+
gh release delete "${{ steps.update_draft_n.outputs.tag_name }}" --repo ${{ github.repository }} --yes
118+
119+
# Delete any existing draft releases for this release branch
120+
for tag in $(gh release list --repo ${{ github.repository }} --json tagName,isPrerelease,isDraft --jq ".[] | select(.isDraft == true and .isPrerelease == false and (.tagName | startswith(\"v$existing_tag_prefix\"))) | .tagName"); do
121+
gh release delete "$tag" --repo ${{ github.repository }} --yes
122+
done
123+
124+
gh release create "$new_tag" \
125+
--repo "${{ github.repository }}" \
126+
--target "${{ env.latest_mu_release_branch_full }}" \
127+
--title "$new_title" \
128+
--notes-file "$release_body_path" \
129+
--draft
130+
env:
131+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
132+
- name: Build a ${{ env.previous_mu_release_branch }} Draft
133+
if: ${{ startsWith(github.ref, env.previous_mu_dev_branch_full) }}
87134
id: update_draft_n_1
88-
uses: release-drafter/release-drafter@v6.0.0
135+
uses: release-drafter/release-drafter@v6.1.0
89136
with:
90137
# Note: Path is relative to .github/
91138
config-name: release-draft-config-n-1.yml
92139
env:
93140
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
141+
- name: Draft Release for N-1 (${{ env.previous_mu_release_branch }}) Release Branch
142+
if: steps.update_draft_n_1.outcome == 'success'
143+
run: |
144+
# Prepare the release body
145+
release_body_path="${{ runner.temp }}/release_body.txt"
146+
release_body=$(cat <<'EOF'
147+
${{ steps.update_draft_n_1.outputs.body }}
148+
EOF
149+
)
150+
release_body="${release_body//\`/\\\`}"
151+
echo "${release_body}" > $release_body_path
152+
sed -i 's/\\`/`/g' $release_body_path
153+
sed -i '/\**Full Changelog\**:/d' $release_body_path
154+
155+
# Get the new tag and title
156+
new_tag=$(echo "${{ steps.update_draft_n_1.outputs.tag_name }}" | sed 's/dev-//')
157+
new_title=$(echo "${{ steps.update_draft_n_1.outputs.tag_name }}" | sed 's/dev/release/')
158+
159+
# Determine the corresponding tag names
160+
existing_tag_prefix=""
161+
tag_regex="v([0-9]{6}).*\."
162+
if [[ $new_tag =~ $tag_regex ]]; then
163+
existing_tag_prefix="${BASH_REMATCH[1]}"
164+
fi
165+
166+
# Delete the template dev draft created
167+
gh release delete "${{ steps.update_draft_n_1.outputs.tag_name }}" --repo ${{ github.repository }} --yes
168+
169+
# Delete any existing draft releases for this release branch
170+
for tag in $(gh release list --repo ${{ github.repository }} --json tagName,isPrerelease,isDraft --jq ".[] | select(.isDraft == true and .isPrerelease == false and (.tagName | startswith(\"v$existing_tag_prefix\"))) | .tagName"); do
171+
gh release delete "$tag" --repo ${{ github.repository }} --yes
172+
done
173+
174+
gh release create "$new_tag" \
175+
--repo "${{ github.repository }}" \
176+
--target "${{ env.previous_mu_release_branch_full }}" \
177+
--title "$new_title" \
178+
--notes-file "$release_body_path" \
179+
--draft
180+
env:
181+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
182+
- name: Create the ${{ env.latest_mu_dev_branch }} Draft
183+
if: ${{ startsWith(github.ref, env.latest_mu_dev_branch_full) }}
184+
uses: release-drafter/[email protected]
185+
with:
186+
# Note: Path is relative to .github/
187+
config-name: release-draft-config-n-dev.yml
188+
env:
189+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
190+
- name: Create the ${{ env.previous_mu_dev_branch }} Draft
191+
if: ${{ startsWith(github.ref, env.previous_mu_dev_branch_full) }}
192+
uses: release-drafter/[email protected]
193+
with:
194+
# Note: Path is relative to .github/
195+
config-name: release-draft-config-n-1-dev.yml
196+
env:
197+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
94198
- name: Build the New Release Draft
95-
if: ${{ !startsWith(github.ref, 'refs/heads/release') }}
199+
if: ${{ !startsWith(github.ref, 'refs/heads/release') && !startsWith(github.ref, 'refs/heads/dev') }}
96200
id: update_draft_non_release
97-
uses: release-drafter/release-drafter@v6.0.0
201+
uses: release-drafter/release-drafter@v6.1.0
98202
with:
99203
# Note: Path is relative to .github/
100204
config-name: release-draft-config.yml

.github/workflows/ReleaseWorkflow.yml

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# @file ReleaseWorkflow.yml
2+
#
3+
# A reusable CI workflow that releases all crates in a repository.
4+
#
5+
##
6+
# Copyright (c) Microsoft Corporation.
7+
# SPDX-License-Identifier: BSD-2-Clause-Patent
8+
##
9+
name: Publish
10+
11+
on:
12+
workflow_call:
13+
secrets:
14+
CRATES_IO_TOKEN:
15+
description: 'The token to use for authenticating with crates.io'
16+
required: true
17+
18+
jobs:
19+
run:
20+
name: Publish
21+
22+
runs-on: ubuntu-latest
23+
24+
permissions:
25+
contents: write
26+
actions: read
27+
28+
steps:
29+
- name: ✅ Checkout Repository ✅
30+
uses: actions/checkout@v4
31+
32+
- name: 🛠️ Download Rust Tools 🛠️
33+
uses: microsoft/mu_devops/.github/actions/rust-tool-cache@main
34+
35+
- name: Get Current Draft Release
36+
id: draft_release
37+
uses: actions/github-script@v7
38+
with:
39+
script: |
40+
const releases = await github.rest.repos.listReleases({
41+
owner: context.repo.owner,
42+
repo: context.repo.repo,
43+
});
44+
45+
const draftReleaseList = releases.data.filter(release => release.draft);
46+
47+
if (draftReleaseList.length === 0) {
48+
core.setFailed("No draft release found. Exiting with error.");
49+
} else if (draftReleaseList.length > 1) {
50+
core.setFailed("Multiple draft releases found. Exiting with error.");
51+
} else {
52+
const draftRelease = draftReleaseList[0];
53+
54+
let tag = draftRelease.tag_name;
55+
if (tag.startsWith('v')) {
56+
tag = tag.slice(1);
57+
}
58+
core.setOutput("id", draftRelease.id);
59+
core.setOutput("tag", tag);
60+
console.log(`Draft Release ID: ${draftRelease.id}`);
61+
console.log(`Draft Release Tag: ${tag}`);
62+
}
63+
64+
- name: Cargo Release Dry Run
65+
run: cargo release ${{ steps.draft_release.outputs.tag }} --workspace
66+
env:
67+
RUSTC_BOOTSTRAP: 1
68+
69+
- name: Login to Crates.io
70+
run: cargo login ${{ secrets.CRATES_IO_TOKEN }}
71+
72+
- name: Update git credentials
73+
run: |
74+
git config --global user.name "github-actions[bot]"
75+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
76+
77+
- name: Cargo Release
78+
run: cargo release ${{ steps.draft_release.outputs.tag }} -x --no-tag --no-confirm --workspace
79+
env:
80+
RUSTC_BOOTSTRAP: 1
81+
82+
- name: Wait for Release Draft Updater
83+
uses: actions/github-script@v7
84+
with:
85+
script: |
86+
const workflowId = "release-draft.yml";
87+
const ref = "main";
88+
const owner = context.repo.owner;
89+
const repo = context.repo.repo;
90+
91+
// Try for 10 minutes. It should only take a few seconds
92+
let maxAttempts = 40;
93+
let attempt = 0;
94+
let completed = false
95+
96+
while (attempt < maxAttempts && !completed) {
97+
await new Promise(resolve => setTimeout(resolve, 15000));
98+
const runs = await github.rest.actions.listWorkflowRuns({
99+
owner,
100+
repo,
101+
workflow_id: workflowId,
102+
branch: ref,
103+
event: 'push',
104+
status: 'in_progress',
105+
});
106+
107+
if (runs.data.workflow_runs.length === 0) {
108+
completed = true;
109+
} else {
110+
attempt++;
111+
}
112+
}
113+
114+
if (!completed) {
115+
core.setFailed("Release Drafter did not complete in time. Please perform the release manually.");
116+
}
117+
118+
- name: Publish Release
119+
uses: actions/github-script@v7
120+
with:
121+
script: |
122+
const releaseId = ${{ steps.draft_release.outputs.id }};
123+
124+
const response = await github.rest.repos.updateRelease({
125+
owner: context.repo.owner,
126+
repo: context.repo.repo,
127+
release_id: releaseId,
128+
draft: false,
129+
});
130+
131+
if (response.status !== 200) {
132+
core.setFailed(`Failed to publish release. Exiting with error.`);
133+
}

.github/workflows/auto-approve.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ jobs:
2929

3030
if: |
3131
github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'uefibot'
32-
uses: microsoft/mu_devops/.github/workflows/AutoApprover.yml@v12.2.0
32+
uses: microsoft/mu_devops/.github/workflows/AutoApprover.yml@v13.0.0
3333
secrets: inherit

.github/workflows/auto-merge.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ jobs:
3232

3333
if: |
3434
github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'uefibot'
35-
uses: microsoft/mu_devops/.github/workflows/AutoMerger.yml@v12.2.0
35+
uses: microsoft/mu_devops/.github/workflows/AutoMerger.yml@v13.0.0
3636
secrets: inherit

.github/workflows/label-sync.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ jobs:
2828
permissions:
2929
issues: write
3030

31-
uses: microsoft/mu_devops/.github/workflows/LabelSyncer.yml@v12.2.0
31+
uses: microsoft/mu_devops/.github/workflows/LabelSyncer.yml@v13.0.0

0 commit comments

Comments
 (0)