1+ # Modified version of https://github.com/easimon/maximize-build-space
2+ name : ' Maximize build disk space'
3+ description : ' Maximize the available disk space for your build job'
4+ branding :
5+ icon : ' crop'
6+ color : ' orange'
7+ inputs :
8+ root-reserve-mb :
9+ description : ' Space to be left free on the root filesystem, in Megabytes.'
10+ required : false
11+ default : ' 1024'
12+
13+ swap-size-mb :
14+ description : ' Swap space to create, in Megabytes.'
15+ required : false
16+ default : ' 4096'
17+ overprovision-lvm :
18+ description : |
19+ Create the LVM disk images as sparse files, making the space required for the LVM image files *appear* unused on the
20+ hosting volumes until actually allocated. Use with care, this can lead to surprising out-of-disk-space situations.
21+ You should prefer adjusting root-reserve-mb/temp-reserve-mb over using this option.
22+ required : false
23+ default : ' false'
24+ build-mount-path :
25+ description : ' Absolute path to the mount point where the build space will be available, defaults to $GITHUB_WORKSPACE if unset.'
26+ required : false
27+ build-mount-path-ownership :
28+ description : ' Ownership of the mount point path, defaults to standard "runner" user and group.'
29+ required : false
30+ default : ' runner:runner'
31+ pv-loop-path :
32+ description : ' Absolute file path for the LVM image created on the root filesystem, the default is usually fine.'
33+ required : false
34+ default : ' /pv.img'
35+
36+ remove-dotnet :
37+ description : ' Removes .NET runtime and libraries. (frees ~17 GB)'
38+ required : false
39+ default : ' false'
40+ remove-android :
41+ description : ' Removes Android SDKs and Tools. (frees ~11 GB)'
42+ required : false
43+ default : ' false'
44+ remove-haskell :
45+ description : ' Removes GHC (Haskell) artifacts. (frees ~2.7 GB)'
46+ required : false
47+ default : ' false'
48+ remove-codeql :
49+ description : ' Removes CodeQL Action Bundles. (frees ~5.4 GB)'
50+ required : false
51+ default : ' false'
52+ remove-docker-images :
53+ description : ' Removes cached Docker images. (frees ~3 GB)'
54+ required : false
55+ default : ' false'
56+ runs :
57+ using : " composite"
58+ steps :
59+ - name : Disk space report before modification
60+ shell : bash
61+ run : |
62+ echo "Memory and swap:"
63+ sudo free -h
64+ echo
65+ sudo swapon --show
66+ echo
67+
68+ echo "Available storage:"
69+ sudo df -h
70+ echo
71+
72+ - name : Maximize build disk space
73+ shell : bash
74+ run : |
75+ set -euo pipefail
76+
77+ BUILD_MOUNT_PATH="${{ inputs.build-mount-path }}"
78+ if [[ -z "${BUILD_MOUNT_PATH}" ]]; then
79+ BUILD_MOUNT_PATH="${GITHUB_WORKSPACE}"
80+ fi
81+
82+ echo "Arguments:"
83+ echo
84+ echo " Root reserve: ${{ inputs.root-reserve-mb }} MiB"
85+
86+ echo " Swap space: ${{ inputs.swap-size-mb }} MiB"
87+ echo " Overprovision LVM: ${{ inputs.overprovision-lvm }}"
88+ echo " Mount path: ${BUILD_MOUNT_PATH}"
89+ echo " Root PV loop path: ${{ inputs.pv-loop-path }}"
90+
91+ echo -n " Removing: "
92+ if [[ ${{ inputs.remove-dotnet }} == 'true' ]]; then
93+ echo -n "dotnet "
94+ fi
95+ if [[ ${{ inputs.remove-android }} == 'true' ]]; then
96+ echo -n "android "
97+ fi
98+ if [[ ${{ inputs.remove-haskell }} == 'true' ]]; then
99+ echo -n "haskell "
100+ fi
101+ if [[ ${{ inputs.remove-codeql }} == 'true' ]]; then
102+ echo -n "codeql "
103+ fi
104+ if [[ ${{ inputs.remove-docker-images }} == 'true' ]]; then
105+ echo -n "docker "
106+ fi
107+ echo
108+
109+ # store owner of $GITHUB_WORKSPACE in case the action deletes it
110+ WORKSPACE_OWNER="$(stat -c '%U:%G' "${GITHUB_WORKSPACE}")"
111+
112+ # ensure mount path exists before the action
113+ sudo mkdir -p "${BUILD_MOUNT_PATH}"
114+ sudo find "${BUILD_MOUNT_PATH}" -maxdepth 0 ! -empty -exec echo 'WARNING: directory [{}] is not empty, data loss might occur. Content:' \; -exec ls -al "{}" \;
115+
116+ echo "Removing unwanted software... "
117+ if [[ ${{ inputs.remove-dotnet }} == 'true' ]]; then
118+ sudo rm -rf /usr/share/dotnet
119+ fi
120+ if [[ ${{ inputs.remove-android }} == 'true' ]]; then
121+ sudo rm -rf /usr/local/lib/android
122+ fi
123+ if [[ ${{ inputs.remove-haskell }} == 'true' ]]; then
124+ sudo rm -rf /opt/ghc
125+ fi
126+ if [[ ${{ inputs.remove-codeql }} == 'true' ]]; then
127+ sudo rm -rf /opt/hostedtoolcache/CodeQL
128+ fi
129+ if [[ ${{ inputs.remove-docker-images }} == 'true' ]]; then
130+ sudo docker image prune --all --force
131+ fi
132+ echo "... done"
133+
134+ VG_NAME=buildvg
135+
136+ # github runners have an active swap file in /mnt/swapfile
137+ # we want to reuse the temp disk, so first unmount swap and clean the temp disk
138+ echo "Unmounting and removing swap file."
139+ sudo swapoff -a
140+ sudo rm -f /mnt/swapfile
141+
142+ echo "Creating LVM Volume."
143+ echo " Creating LVM PV on root fs."
144+ # create loop pv image on root fs
145+ ROOT_RESERVE_KB=$(expr ${{ inputs.root-reserve-mb }} \* 1024)
146+ ROOT_FREE_KB=$(df --block-size=1024 --output=avail / | tail -1)
147+ ROOT_LVM_SIZE_KB=$(expr $ROOT_FREE_KB - $ROOT_RESERVE_KB)
148+ ROOT_LVM_SIZE_BYTES=$(expr $ROOT_LVM_SIZE_KB \* 1024)
149+ sudo touch "${{ inputs.pv-loop-path }}" && sudo fallocate -z -l "${ROOT_LVM_SIZE_BYTES}" "${{ inputs.pv-loop-path }}"
150+ export ROOT_LOOP_DEV=$(sudo losetup --find --show "${{ inputs.pv-loop-path }}")
151+ sudo pvcreate -f "${ROOT_LOOP_DEV}"
152+
153+
154+
155+ # create volume group from these pvs
156+ sudo vgcreate "${VG_NAME}" "${ROOT_LOOP_DEV}"
157+
158+ echo "Recreating swap"
159+ # create and activate swap
160+ sudo lvcreate -L "${{ inputs.swap-size-mb }}M" -n swap "${VG_NAME}"
161+ sudo mkswap "/dev/mapper/${VG_NAME}-swap"
162+ sudo swapon "/dev/mapper/${VG_NAME}-swap"
163+
164+ echo "Creating build volume"
165+ # create and mount build volume
166+ sudo lvcreate -l 100%FREE -n buildlv "${VG_NAME}"
167+ if [[ ${{ inputs.overprovision-lvm }} == 'true' ]]; then
168+ sudo mkfs.ext4 -m0 "/dev/mapper/${VG_NAME}-buildlv"
169+ else
170+ sudo mkfs.ext4 -Enodiscard -m0 "/dev/mapper/${VG_NAME}-buildlv"
171+ fi
172+ sudo mount "/dev/mapper/${VG_NAME}-buildlv" "${BUILD_MOUNT_PATH}"
173+ sudo chown -R "${{ inputs.build-mount-path-ownership }}" "${BUILD_MOUNT_PATH}"
174+
175+ # if build mount path is a parent of $GITHUB_WORKSPACE, and has been deleted, recreate it
176+ if [[ ! -d "${GITHUB_WORKSPACE}" ]]; then
177+ sudo mkdir -p "${GITHUB_WORKSPACE}"
178+ sudo chown -R "${WORKSPACE_OWNER}" "${GITHUB_WORKSPACE}"
179+ fi
180+
181+ - name : Disk space report after modification
182+ shell : bash
183+ run : |
184+ echo "Memory and swap:"
185+ sudo free -h
186+ echo
187+ sudo swapon --show
188+ echo
189+
190+ echo "Available storage:"
191+ sudo df -h
0 commit comments