Skip to content
Merged
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
58 changes: 58 additions & 0 deletions .github/workflows/cli-release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,35 @@ jobs:
mkdir -p "$LEGACY_DIR/ripgrep"
tar -xzf "$LEGACY_DIR/ripgrep.tar.gz" \
-C "$LEGACY_DIR/ripgrep" --strip-components=1

# Select a usable Xcode with clang before cargo needs a C linker.
# Some runner images leave a broken default (e.g. Xcode_15.4 without clang).
DEVELOPER_DIR=""
CANDIDATES=()
while IFS= read -r app; do
CANDIDATES+=("$app")
done < <(ls -1d /Applications/Xcode_*.app 2>/dev/null | sort -V -r || true)
if [[ -d /Applications/Xcode.app ]]; then
CANDIDATES+=("/Applications/Xcode.app")
fi
for app in "${CANDIDATES[@]}"; do
if [[ -x "$app/Contents/Developer/usr/bin/clang" ]]; then
DEVELOPER_DIR="$app/Contents/Developer"
break
fi
done
if [[ -z "$DEVELOPER_DIR" ]]; then
echo "error: no Xcode app with an executable clang under /Applications" >&2
echo "Available apps:" >&2
ls -la /Applications/Xcode*.app 2>/dev/null || echo "(none)" >&2
exit 1
fi
sudo xcode-select -s "$DEVELOPER_DIR"
export DEVELOPER_DIR
echo "Selected DEVELOPER_DIR=$DEVELOPER_DIR"
xcodebuild -version
clang --version

pushd "$LEGACY_DIR/ripgrep"
MACOSX_DEPLOYMENT_TARGET=11.0 cargo build --release --locked
popd
Expand All @@ -239,6 +268,35 @@ jobs:
https://github.com/BurntSushi/ripgrep/archive/refs/tags/14.1.1.tar.gz
tar -xzf "$RG_DIR/ripgrep.tar.gz" \
-C "$RG_DIR/source" --strip-components=1

# Select a usable Xcode with clang before cargo needs a C linker.
# Some runner images leave a broken default (e.g. Xcode_15.4 without clang).
DEVELOPER_DIR=""
CANDIDATES=()
while IFS= read -r app; do
CANDIDATES+=("$app")
done < <(ls -1d /Applications/Xcode_*.app 2>/dev/null | sort -V -r || true)
if [[ -d /Applications/Xcode.app ]]; then
CANDIDATES+=("/Applications/Xcode.app")
fi
for app in "${CANDIDATES[@]}"; do
if [[ -x "$app/Contents/Developer/usr/bin/clang" ]]; then
DEVELOPER_DIR="$app/Contents/Developer"
break
fi
done
if [[ -z "$DEVELOPER_DIR" ]]; then
echo "error: no Xcode app with an executable clang under /Applications" >&2
echo "Available apps:" >&2
ls -la /Applications/Xcode*.app 2>/dev/null || echo "(none)" >&2
exit 1
fi
sudo xcode-select -s "$DEVELOPER_DIR"
export DEVELOPER_DIR
echo "Selected DEVELOPER_DIR=$DEVELOPER_DIR"
xcodebuild -version
clang --version

pushd "$RG_DIR/source"
MACOSX_DEPLOYMENT_TARGET=13.0 cargo build --release --locked
popd
Expand Down
34 changes: 34 additions & 0 deletions scripts/__tests__/release-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ const workflow = readFileSync(
'utf8',
)

const buildWorkflow = readFileSync(
resolve(import.meta.dir, '../../.github/workflows/cli-release-build.yml'),
'utf8',
)

describe('production release workflow', () => {
test('builds the committed release source before creating its tag', () => {
const prepareStart = workflow.indexOf(' prepare-and-commit-prod:')
Expand Down Expand Up @@ -42,3 +47,32 @@ describe('production release workflow', () => {
expect(workflow).toContain('test "$existing_commit" = "$RELEASE_COMMIT"')
})
})

describe('CLI release build workflow', () => {
test('selects a usable Xcode before macOS cargo builds that need a C linker', () => {
const legacyStep = 'Prepare macOS 11 legacy toolchain'
const intelRipgrepStep = 'Rebuild Intel ripgrep for macOS 13'
const legacyStart = buildWorkflow.indexOf(legacyStep)
const intelStart = buildWorkflow.indexOf(intelRipgrepStep)
const legacyCargo = buildWorkflow.indexOf(
'MACOSX_DEPLOYMENT_TARGET=11.0 cargo build --release --locked',
)
const intelCargo = buildWorkflow.indexOf(
'MACOSX_DEPLOYMENT_TARGET=13.0 cargo build --release --locked',
)

expect(legacyStart).toBeGreaterThan(-1)
expect(intelStart).toBeGreaterThan(-1)
expect(legacyCargo).toBeGreaterThan(legacyStart)
expect(intelCargo).toBeGreaterThan(intelStart)

const legacyBlock = buildWorkflow.slice(legacyStart, legacyCargo)
const intelBlock = buildWorkflow.slice(intelStart, intelCargo)

for (const block of [legacyBlock, intelBlock]) {
expect(block).toContain('xcode-select -s')
expect(block).toContain('export DEVELOPER_DIR')
expect(block).toContain('/Contents/Developer/usr/bin/clang')
}
})
})
Loading