-
-
Notifications
You must be signed in to change notification settings - Fork 346
189 lines (168 loc) · 8 KB
/
caching.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
name: Caching
# Docs on the workflow:
# 1. GitHub cache scoping goes:
# [main branch -> PR main branch -> PR. (essentially in a tree fashion)](https://web.archive.org/web/20211125171853/https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache).
# Building & keeping caches on `master` allows
# to share the main project state cache be shared to the whole tree.
# 2. GitHub has a [default 10G cache pool limit](https://web.archive.org/web/20211125171853/https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy) per repo.
# HLS is a big monorepo codebase, which means easy cache pool
# invalidation & exhaustion because of the pool limit.
# To keep caches useful - the main state of the main branch should remain
# & so keep caching in the repo well below the limit.
# that means preferring main branch to the PR caches
# (especially internal branch ones), since PRs from internal branches -
# count into the repo 10G pool, while that cache gets used only inside of the PR,
# while exhausting the pool would bork cache for the rest of the community.
# That is a short story why `dist-newstyle` (especially full) currently is not
# includded into `master` or PR caches.
defaults:
run:
shell: bash
# See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency.
concurrency:
group: ${{ github.head_ref }}-${{ github.workflow }}
cancel-in-progress: true
on:
workflow_dispatch:
push:
branches:
- master
schedule:
# Refresh snapshot every (02+8*x):25 UTC
# When cache is present it is a light check workflow with early termination.
# When primary cache is not hit - runs the cache generation.
# Why: GitHub repo has 10G pool & on overflow GitHub removes caches in FIFO manner.
# When internal branche PRs save into the same pool -
# their cache is accessible only inside of the scope of the PR.
# If main cache is forced out - there are no cache shared between PRs,
# which implies all PRs would start to create & save their cache.
# Reinstitution of the main chache puts it back into FIFO
# & so it gets shared across all PRs.
- cron: "25 2/8 * * *"
env:
cabalBuild: "v2-build all --enable-tests --enable-benchmarks --keep-going"
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v3.4.1
with:
cancel_others: false
paths_ignore: '["**/docs/**", "**.md", "**/LICENSE", "install/**", "**.nix", "flake.lock", "**/README.md", "FUNDING.yml", ".circleci/**"]'
caching:
if: needs.pre_job.outputs.should_skip != 'true'
needs: pre_job
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
ghc: ["9.0.1", '8.10.7', '8.10.6', "8.8.4", "8.6.5"]
os: [ubuntu-latest, macOS-latest, windows-latest]
cabal: ['3.6']
steps:
- uses: actions/checkout@v2
- uses: haskell/actions/setup@v1
id: HaskEnvSetup
with:
ghc-version : ${{ matrix.ghc }}
cabal-version: ${{ matrix.cabal }}
enable-stack: false
- if: runner.os == 'Windows'
name: (Windows) Platform config
run: |
echo "CABAL_PKGS_DIR=C:\\cabal\\packages" >> $GITHUB_ENV
- if: ( runner.os == 'Linux' ) || ( runner.os == 'macOS' )
name: (Linux,macOS) Platform config
run: |
echo "CABAL_PKGS_DIR=~/.cabal/packages" >> $GITHUB_ENV
# Needs to be before Cache Cabal so the cache can detect changes to the modified cabal.project file
- if: matrix.ghc == '9.0.1'
name: (GHC 9.0.1) Use modified `cabal.project`
run: |
# File has some protections preventing regular `rm`.
# (most probably sticky bit is set on $HOME)
# `&&` insures `rm -f` return is positive.
# Many platforms also have `alias cp='cp -i'`.
rm -f -v cabal.project && cp -v cabal-ghc901.project cabal.project
- if: runner.os == 'Windows' && matrix.ghc == '8.8.4'
name: (Windows,GHC 8.8) Modify `cabal.project` to workaround segfaults
run: |
echo "package floskell" >> cabal.project
echo " ghc-options: -O0" >> cabal.project
# Shorten binary names as a workaround for filepath length limits in Windows,
# but since tests are hardcoded on this workaround -
# all platforms (in 2021-12-07) need it.
# All workflows which distinquishes cache on `cabal.project` needs this.
- name: Workaround shorten binary names
run: |
sed -i.bak -e 's/haskell-language-server/hls/g' \
-e 's/haskell_language_server/hls/g' \
haskell-language-server.cabal cabal.project
sed -i.bak -e 's/Paths_haskell_language_server/Paths_hls/g' \
src/**/*.hs exe/*.hs
- name: Retrieving `cabal.project` Hackage timestamp
run: |
# Form: index-state: 2021-11-29T08:11:08Z
INDEX_STATE_ENTRY=$(grep index-state cabal.project)
# Form: 2021-11-29T08-11-08Z
INDEX_STATE1=$(echo "$INDEX_STATE_ENTRY" | cut -d' ' -f2 | tr ':' '-')
echo "INDEX_STATE=$INDEX_STATE1" >> $GITHUB_ENV
- name: Form the package list ('cabal.project.freeze')
continue-on-error: true
run: |
cabal v2-freeze
echo ''
echo 'Output:'
echo ''
cat 'cabal.project.freeze'
# 2021-12-02: NOTE: Cabal Hackage source tree storage does not depend on OS or GHC really,
# but can depend on `base`.
# But this caching is happens only inside `master` for `master` purposes of compiling the deps
# so having a shared pool here that depends only on Hackage pin & does not depend on `base` is "good enough"
# & used such because it preserves 10% of a global cache storage pool.
- name: Hackage sources cache
uses: actions/cache@v2
env:
cache-name: hackage-sources
with:
path: ${{ env.CABAL_PKGS_DIR }}
key: ${{ env.cache-name }}-${{ env.INDEX_STATE }}-${{ hashFiles('cabal.project.freeze') }}
restore-keys: |
${{ env.cache-name }}-${{ env.INDEX_STATE }}-
${{ env.cache-name }}-
- name: Compiled deps cache
id: compiled-deps
uses: actions/cache@v2
env:
cache-name: compiled-deps
with:
path: ${{ steps.HaskEnvSetup.outputs.cabal-store }}
key: ${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.INDEX_STATE }}-${{ hashFiles('cabal.project.freeze') }}
restore-keys: |
${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.INDEX_STATE }}-
${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-
${{ env.cache-name }}-${{ runner.os }}-
- if: steps.compiled-deps.outputs.cache-hit != 'true'
run: |
cabal update
- if: steps.compiled-deps.outputs.cache-hit != 'true'
name: Download all sources
run: |
cabal $cabalBuild --only-download
# repeating builds to workaround segfaults in windows and ghc-8.8.4
# This build agenda in not to have successful code,
# but to cache what can be cached, so step is fault tolerant & would always succseed.
# 2021-12-11: NOTE: Building all targets, since
# current Cabal does not allow `all --enable-tests --enable-benchmarks --only-dependencies`
- if: steps.compiled-deps.outputs.cache-hit != 'true'
name: Build all targets; try 3 times
continue-on-error: true
run: |
cabal $cabalBuild || cabal $cabalBuild || cabal $cabalBuild
# Despite the `continue-on-error: true` directive - CI does not ignore the return code of the last step
- name: Workaround to CI platform
run: |
true