mirror of
https://github.com/bitwarden/ios.git
synced 2025-12-11 04:34:55 -06:00
[PM-26455] Improve CI runtimes by disabling cpu intensive processes (#1995)
This commit is contained in:
parent
11f7358bd8
commit
0b9b9d89c4
84
.github/actions/macos-runner-tuneup/action.yml
vendored
Normal file
84
.github/actions/macos-runner-tuneup/action.yml
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
name: 'macOS Runner Tuneup'
|
||||
description: 'Optimizes macOS GitHub runners by disabling resource-heavy background processes'
|
||||
author: 'Bitwarden'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Optimize macOS Runner
|
||||
shell: bash
|
||||
run: |
|
||||
echo "🚀 Starting macOS Runner Tuneup..."
|
||||
echo "=================================="
|
||||
|
||||
echo "🔍 Disabling Spotlight..."
|
||||
sudo mdutil -a -i off # disables indexing on all volumes
|
||||
sudo mdutil -a -d # disables spotlight activity on all volumes
|
||||
|
||||
echo "🔍 Disabling Spotlight Knowledge Daemon..."
|
||||
sudo launchctl disable system/com.apple.spotlightknowledged || true
|
||||
sudo pkill -SIGKILL spotlightknowledged || true
|
||||
|
||||
echo "🛑 Disabling metadata services..."
|
||||
sudo launchctl disable system/com.apple.metadata.mds || true
|
||||
sudo launchctl disable system/com.apple.metadata.mds.index || true
|
||||
sudo launchctl disable system/com.apple.metadata.mds.scan || true
|
||||
|
||||
echo "📦 Stopping metadata services..."
|
||||
sudo launchctl bootout system/com.apple.metadata.mds || true
|
||||
sudo launchctl bootout system/com.apple.metadata.mds.index || true
|
||||
sudo launchctl bootout system/com.apple.metadata.mds.scan || true
|
||||
sudo launchctl bootout system/com.apple.metadata.mdwrite || true
|
||||
|
||||
echo "⚡ Killing metadata processes..."
|
||||
sudo pkill -SIGKILL -f "Metadata.framework/Versions/A/Support/mds" || true
|
||||
sudo pkill -SIGKILL Spotlight || true
|
||||
echo "✅ Spotlight disabled!"
|
||||
|
||||
echo "💥 Disabling ReportCrash..."
|
||||
sudo launchctl disable system/com.apple.ReportCrash || true
|
||||
sudo launchctl disable system/com.apple.ReportCrash.Root || true
|
||||
|
||||
echo "💥 Unloading ReportCrash..."
|
||||
sudo launchctl bootout system/com.apple.ReportCrash || true
|
||||
sudo launchctl bootout system/com.apple.ReportCrash.Root || true
|
||||
|
||||
sudo defaults write com.apple.CrashReporter DialogType none || true
|
||||
echo "✅ ReportCrash disabled!"
|
||||
|
||||
echo "🌱 Disabling EcosystemD..."
|
||||
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ecosystemd.plist || true
|
||||
sudo pkill -SIGKILL -f "ecosystemd" || true
|
||||
echo "✅ EcosystemD disabled!"
|
||||
|
||||
echo "🌱 Disabling EcosystemAnalyticsD..."
|
||||
sudo launchctl bootout system/com.apple.ecosystemanalyticsd || true
|
||||
echo "✅ EcosystemAnalyticsD disabled!"
|
||||
|
||||
echo "🌱 Disabling SubmitDiagInfo..."
|
||||
sudo defaults write /Library/Preferences/com.apple.SubmitDiagInfo AutoSubmit -bool false || true
|
||||
|
||||
echo "🌍 Disabling location services..."
|
||||
sudo defaults write /Library/Preferences/com.apple.locationd.plist LocationServicesEnabled -int 0 || true
|
||||
|
||||
echo "🔍 Disabling Siri..."
|
||||
sudo defaults write com.apple.assistant.support Assistant\ Enabled -bool false || true
|
||||
sudo defaults write com.apple.Siri StatusMenuVisible -bool false || true
|
||||
|
||||
echo "🔒 Disabling iCloud analytics and usage tracking..."
|
||||
sudo defaults write com.apple.UsageTracking CoreDonationsEnabled -bool false || true
|
||||
sudo defaults write com.apple.UsageTracking UDCAutomationEnabled -bool false || true
|
||||
|
||||
echo "🔍 Disabling Spotlight suggestions..."
|
||||
sudo defaults write com.apple.lookup.shared LookupSuggestionsDisabled -bool true || true
|
||||
|
||||
echo "📊 Process Information After Tuning"
|
||||
echo "=================================="
|
||||
echo "🧠 Sorted by memory usage:"
|
||||
head -n20 < <(ps -emo pid,pcpu,pmem,comm)
|
||||
echo ""
|
||||
echo "🔥 Sorted by CPU usage:"
|
||||
head -n20 < <(ps -ero pid,pcpu,pmem,comm)
|
||||
echo ""
|
||||
echo "🎉 macOS Runner Tuneup Complete!"
|
||||
|
||||
3
.github/workflows/_build-any.yml
vendored
3
.github/workflows/_build-any.yml
vendored
@ -55,6 +55,9 @@ jobs:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Optimize macOS Runner
|
||||
uses: ./.github/actions/macos-runner-tuneup
|
||||
|
||||
- name: Read Xcode version from file if not provided
|
||||
run: |
|
||||
if [ -z "$_XCODE_VERSION" ]; then
|
||||
|
||||
9
.github/workflows/test-bwa.yml
vendored
9
.github/workflows/test-bwa.yml
vendored
@ -60,7 +60,7 @@ jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: macos-26
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 50
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@ -73,6 +73,9 @@ jobs:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Optimize macOS Runner
|
||||
uses: ./.github/actions/macos-runner-tuneup
|
||||
|
||||
- name: Read Xcode version and simulator configuration from file if not provided
|
||||
run: |
|
||||
if [ -z "$_XCODE_VERSION" ]; then
|
||||
@ -123,6 +126,7 @@ jobs:
|
||||
|
||||
- name: Build and test
|
||||
run: |
|
||||
python Scripts/pyeetd/main.py & PYEETD_PID=$!
|
||||
xcrun xcodebuild test \
|
||||
-workspace Bitwarden.xcworkspace \
|
||||
-scheme Authenticator \
|
||||
@ -132,7 +136,10 @@ jobs:
|
||||
-derivedDataPath build/DerivedData \
|
||||
-test-timeouts-enabled yes \
|
||||
-maximum-test-execution-time-allowance 1 \
|
||||
-retry-tests-on-failure \
|
||||
-test-repetition-relaunch-enabled YES \
|
||||
-quiet
|
||||
kill $PYEETD_PID
|
||||
|
||||
- name: Print Logs Summary
|
||||
if: always()
|
||||
|
||||
17
.github/workflows/test.yml
vendored
17
.github/workflows/test.yml
vendored
@ -55,7 +55,7 @@ jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: macos-26
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 50
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@ -68,6 +68,9 @@ jobs:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Optimize macOS Runner
|
||||
uses: ./.github/actions/macos-runner-tuneup
|
||||
|
||||
- name: Read Xcode version and simulator configuration from file if not provided
|
||||
run: |
|
||||
if [ -z "$_XCODE_VERSION" ]; then
|
||||
@ -118,6 +121,7 @@ jobs:
|
||||
|
||||
- name: Build and test
|
||||
run: |
|
||||
python Scripts/pyeetd/main.py & PYEETD_PID=$!
|
||||
xcrun xcodebuild test \
|
||||
-workspace Bitwarden.xcworkspace \
|
||||
-scheme Bitwarden \
|
||||
@ -127,7 +131,18 @@ jobs:
|
||||
-derivedDataPath build/DerivedData \
|
||||
-test-timeouts-enabled yes \
|
||||
-maximum-test-execution-time-allowance 1 \
|
||||
-retry-tests-on-failure \
|
||||
-test-repetition-relaunch-enabled YES \
|
||||
-quiet
|
||||
kill $PYEETD_PID
|
||||
|
||||
- name: Output processes
|
||||
run: |
|
||||
echo "Sorted by memory usage"
|
||||
ps -em -o pid,pcpu,pmem,comm | head -n40
|
||||
echo "--------------------------------"
|
||||
echo "Sorted by CPU usage"
|
||||
ps -er -o pid,pcpu,pmem,comm | head -n40
|
||||
|
||||
- name: Print Logs Summary
|
||||
if: always()
|
||||
|
||||
1
Scripts/pyeetd/.python-version
Normal file
1
Scripts/pyeetd/.python-version
Normal file
@ -0,0 +1 @@
|
||||
3.12
|
||||
139
Scripts/pyeetd/main.py
Normal file
139
Scripts/pyeetd/main.py
Normal file
@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
pyeetd - based on https://github.com/biscuitehh/yeetd
|
||||
|
||||
how to use:
|
||||
python Scripts/pyeetd/main.py & PYEETD_PID=$!
|
||||
...
|
||||
kill $PYEETD_PID
|
||||
"""
|
||||
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
import subprocess
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
|
||||
OS_PROCESSES = {
|
||||
"Spotlight",
|
||||
"ReportCrash",
|
||||
"ecosystemanalyticsd"
|
||||
"com.apple.ecosystemd",
|
||||
"com.apple.metadata.mds",
|
||||
}
|
||||
|
||||
SIMULATOR_PROCESSES = {
|
||||
"AegirPoster",
|
||||
"InfographPoster",
|
||||
"CollectionsPoster",
|
||||
"ExtragalacticPoster",
|
||||
"KaleidoscopePoster",
|
||||
"EmojiPosterExtension",
|
||||
"AmbientPhotoFramePosterProvider",
|
||||
"PhotosPosterProvider",
|
||||
"AvatarPosterExtension",
|
||||
"GradientPosterExtension",
|
||||
"MonogramPosterExtension"
|
||||
}
|
||||
|
||||
SIMULATOR_PATH_SEARCH_KEY = "simruntime/Contents/Resources/RuntimeRoot"
|
||||
|
||||
# How long to sleep between checks in seconds
|
||||
SLEEP_DELAY = 5
|
||||
|
||||
# How often to print process info (in seconds)
|
||||
PRINT_PROCESSES_INTERVAL = 60
|
||||
|
||||
@dataclass
|
||||
class ProcessInfo:
|
||||
pid: int
|
||||
cpu_percent: float
|
||||
memory_percent: float
|
||||
name: str
|
||||
is_simulator: bool
|
||||
|
||||
@property
|
||||
def environment(self) -> str:
|
||||
return "Simulator" if self.is_simulator else "OS"
|
||||
|
||||
@property
|
||||
def output_string(self) -> str:
|
||||
return f"{self.pid}\t{self.cpu_percent}%\t{self.memory_percent}%\t{self.name}\t{self.environment}"
|
||||
|
||||
class ProcessSort(Enum):
|
||||
CPU = "cpu"
|
||||
MEMORY = "memory"
|
||||
|
||||
def get_processes(sort_by=ProcessSort.CPU):
|
||||
"""Get all processes using ps command - equivalent to Swift's proc_listallpids"""
|
||||
sorty_by = "-ero" if sort_by == ProcessSort.CPU else "-emo"
|
||||
result = subprocess.run(['ps', sorty_by, 'pid,pcpu,pmem,comm'],
|
||||
capture_output=True, text=True, check=True)
|
||||
processes = []
|
||||
|
||||
for line in result.stdout.splitlines()[1:]: # Skip header
|
||||
parts = line.strip().split(None, 3)
|
||||
if len(parts) >= 3:
|
||||
pid = int(parts[0])
|
||||
cpu_percent = float(parts[1])
|
||||
memory_percent = float(parts[2])
|
||||
name = parts[3]
|
||||
is_simulator = SIMULATOR_PATH_SEARCH_KEY in name
|
||||
processes.append(ProcessInfo(pid, cpu_percent, memory_percent, name, is_simulator))
|
||||
|
||||
return processes
|
||||
|
||||
def print_processes(processes, limit=-1):
|
||||
output = []
|
||||
output.append("================================")
|
||||
output.append("⚡️ Processes sorted by CPU usage:")
|
||||
output.append("PID\tCPU%\tMemory%\tName\tEnvironment")
|
||||
limit = len(processes) if limit == -1 else limit
|
||||
for p in processes[:limit]:
|
||||
output.append(p.output_string)
|
||||
|
||||
output.append("--------------------------------")
|
||||
output.append("🧠 Processes sorted by memory usage:")
|
||||
output.append("PID\tCPU%\tMemory%\tName\tEnvironment")
|
||||
processes_sorted_by_memory = sorted(processes, key=lambda x: x.memory_percent, reverse=True)
|
||||
for p in processes_sorted_by_memory[:limit]:
|
||||
output.append(p.output_string)
|
||||
|
||||
output.append("================================")
|
||||
print("\n".join(output))
|
||||
|
||||
def find_unwanted(processes):
|
||||
yeeting = []
|
||||
for p in processes:
|
||||
process_target_list = SIMULATOR_PROCESSES if p.is_simulator else OS_PROCESSES
|
||||
for k in process_target_list:
|
||||
if k in p.name:
|
||||
yeeting.append(p)
|
||||
return yeeting
|
||||
|
||||
def yeet(processes):
|
||||
output = []
|
||||
for p in processes:
|
||||
output.append(f"🤠 pyeetd: Stopping - {p.output_string}")
|
||||
os.killpg(p.pid, signal.SIGKILL)
|
||||
return output
|
||||
|
||||
def main():
|
||||
print_cycles = PRINT_PROCESSES_INTERVAL // SLEEP_DELAY
|
||||
i = 0
|
||||
while True:
|
||||
output = []
|
||||
processes = get_processes(ProcessSort.CPU)
|
||||
processes_to_yeet = find_unwanted(processes)
|
||||
output.extend(yeet(processes_to_yeet))
|
||||
output.append(f"🤠 {time.strftime('%Y-%m-%d %H:%M:%S')} - pyeetd {len(processes_to_yeet)} processes.")
|
||||
print("\n".join(output))
|
||||
if i % print_cycles == 0:
|
||||
print_processes(processes, 10)
|
||||
i += 1
|
||||
time.sleep(SLEEP_DELAY)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
x
Reference in New Issue
Block a user