Skip to content

Commit 298e8e0

Browse files
committed
feat: move shell runs from main workflow to composite action
1 parent c6927a7 commit 298e8e0

File tree

1 file changed

+4
-247
lines changed

1 file changed

+4
-247
lines changed

.github/workflows/pr-differences-mutants.yml

Lines changed: 4 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -29,108 +29,8 @@ jobs:
2929
small_packages_with_shards: ${{ steps.check_packages_and_shards.outputs.small_packages_with_shards }}
3030

3131
steps:
32-
- name: Checkout repo
33-
uses: actions/checkout@v3
34-
with:
35-
fetch-depth: 0
36-
37-
- name: Install cargo-mutants
38-
run: cargo install --version 23.12.2 cargo-mutants
39-
40-
- name: Relative diff
41-
run: |
42-
git diff origin/${{ github.base_ref }}.. > git.diff
43-
44-
- name: Update git diff
45-
run: |
46-
input_file="git.diff"
47-
temp_file="temp_diff_file.diff"
48-
49-
# Check if the commands exist on the host
50-
for cmd in tac awk sed; do
51-
command -v "${cmd}" > /dev/null 2>&1 || echo "Missing command: ${cmd}"
52-
done
53-
54-
# Reverse the file, remove 4 lines after '+++ /dev/null', then reverse it back (editors can't go backwards - to remove lines above)
55-
tac "$input_file" > "$temp_file" && mv "$temp_file" "$input_file"
56-
sed '/+++ \/dev\/null/{n;N;N;N;d;}' "$input_file" > "$temp_file" && mv "$temp_file" "$input_file"
57-
tac "$input_file" > "$temp_file" && mv "$temp_file" "$input_file"
58-
59-
# Remove the lines between '+++ /dev/null' (included) and 'diff --git a/'
60-
awk '
61-
BEGIN { in_block=0 }
62-
/\+\+\+ \/dev\/null/ { in_block=1; next }
63-
in_block && /diff --git a\// { in_block=0; print; next }
64-
!in_block
65-
' "$input_file" > "$temp_file" && mv "$temp_file" "$input_file"
66-
67-
- name: Split diffs
68-
run: |
69-
cargo mutants --in-diff git.diff --list > all_mutants.txt
70-
mkdir -p mutants_by_packages
71-
72-
# Check that the file exists before performing actions on it
73-
if [ -s all_mutants.txt ]; then
74-
echo "The file containing mutants is missing or empty!"
75-
exit 1
76-
fi
77-
78-
# Split the differences from git into 2 parts, big packages ('stacks-node' and 'stackslib') and small packages (all others) and put them into separate files
79-
while IFS= read -r line; do
80-
package=$(echo "$line" | cut -d'/' -f1)
81-
if [[ $package == "testnet" || $package == "stackslib" ]]; then
82-
echo "$line" >> "mutants_by_packages/big_packages.txt"
83-
else
84-
echo "$line" >> "mutants_by_packages/small_packages.txt"
85-
fi
86-
done < all_mutants.txt
87-
88-
- name: Check packages and shards
89-
id: check_packages_and_shards
90-
run: |
91-
number_of_big_mutants=0
92-
number_of_small_mutants=0
93-
94-
# If big_packages file exists, count how many mutants there are
95-
if [[ -s mutants_by_packages/big_packages.txt ]]; then
96-
number_of_big_mutants=$(cat mutants_by_packages/big_packages.txt | awk 'END { print NR }' | tr -d '[:space:]')
97-
fi
98-
99-
# If small_packages file exists, count how many mutants there are
100-
if [[ -s mutants_by_packages/small_packages.txt ]]; then
101-
number_of_small_mutants=$(cat mutants_by_packages/small_packages.txt | awk 'END { print NR }' | tr -d '[:space:]')
102-
fi
103-
104-
# Set the mutants limit for when to run with shards on the small packages
105-
if [[ $number_of_big_mutants -gt 15 ]]; then
106-
small_packages_shard_limit=119
107-
else
108-
small_packages_shard_limit=79
109-
fi
110-
111-
# If there are mutants from big packages, check whether to run with or without shards, otherwise there's nothing to run
112-
if [[ $number_of_big_mutants -ne 0 ]]; then
113-
echo "run_big_packages=true" >> "$GITHUB_OUTPUT"
114-
if [[ $number_of_big_mutants -gt 15 ]]; then
115-
echo "big_packages_with_shards=true" >> "$GITHUB_OUTPUT"
116-
else
117-
echo "big_packages_with_shards=false" >> "$GITHUB_OUTPUT"
118-
fi
119-
else
120-
echo "run_big_packages=false" >> "$GITHUB_OUTPUT"
121-
fi
122-
123-
# If there are mutants from small packages, check whether to run with or without shards, otherwise there's nothing to run
124-
if [[ $number_of_small_mutants -ne 0 ]]; then
125-
echo "run_small_packages=true" >> "$GITHUB_OUTPUT"
126-
if [[ $number_of_small_mutants -gt $small_packages_shard_limit ]]; then
127-
echo "small_packages_with_shards=true" >> "$GITHUB_OUTPUT"
128-
else
129-
echo "small_packages_with_shards=false" >> "$GITHUB_OUTPUT"
130-
fi
131-
else
132-
echo "run_small_packages=false" >> "$GITHUB_OUTPUT"
133-
fi
32+
- id: check_packages_and_shards
33+
uses: stacks-network/actions/mutation-testing/check-packages-and-shards@feat/mutation-testing
13434

13535
# Mutation testing - Execute on PR on small packages that have functions modified (normal run, no shards)
13636
pr-differences-mutants-small-normal:
@@ -230,148 +130,5 @@ jobs:
230130
]
231131

232132
steps:
233-
- name: Download artifacts
234-
uses: actions/download-artifact@v3
235-
236-
- name: Append output from shards
237-
run: |
238-
folders=("mutants-shard-big--1" "mutants-shard-big-0" "mutants-shard-big-1" "mutants-shard-big-2" "mutants-shard-big-3" "mutants-shard-big-4" "mutants-shard-big-5" "mutants-shard-big-6" "mutants-shard-big-7" "mutants-shard-small--1" "mutants-shard-small-0" "mutants-shard-small-1" "mutants-shard-small-2" "mutants-shard-small-3")
239-
files=("missed.txt" "caught.txt" "timeout.txt" "unviable.txt")
240-
mkdir -p mutants-shards
241-
242-
for file in "${files[@]}"; do
243-
for folder in "${folders[@]}"; do
244-
if [[ -s "$folder/$file" ]]; then
245-
cat "$folder/$file" >> "mutants-shards/$file"
246-
fi
247-
done
248-
done
249-
250-
for folder in "${folders[@]}"; do
251-
if [[ -s "$folder/exit_code.txt" ]]; then
252-
exit_code=$(<"${folder}/exit_code.txt")
253-
most_relevant_exit_code=0
254-
255-
case $exit_code in
256-
4)
257-
most_relevant_exit_code=4
258-
;;
259-
1)
260-
[ "$most_relevant_exit_code" -eq 0 ] && most_relevant_exit_code=1
261-
;;
262-
2)
263-
[ "$most_relevant_exit_code" -eq 0 ] && most_relevant_exit_code=2
264-
;;
265-
3)
266-
[ "$most_relevant_exit_code" -eq 0 ] && most_relevant_exit_code=3
267-
;;
268-
0)
269-
;;
270-
*)
271-
echo "Unknown exit code $exit_code"
272-
most_relevant_exit_code=$exit_code
273-
;;
274-
esac
275-
fi
276-
done
277-
278-
echo "$most_relevant_exit_code" > './mutants-shards/exit_code.txt'
279-
280-
- name: Print mutants
281-
run: |
282-
server_url="${{ github.server_url }}"
283-
organisation="${{ github.repository_owner }}"
284-
repository="${{ github.event.repository.name }}"
285-
commit="${{ github.sha }}"
286-
287-
write_section() {
288-
local section_title=$1
289-
local file_name=$2
290-
291-
if [ -s "$file_name" ]; then
292-
if [[ "$section_title" != "" ]]; then
293-
echo "## $section_title" >> "$GITHUB_STEP_SUMMARY"
294-
fi
295-
296-
if [[ "$section_title" == "Missed:" ]]; then
297-
echo "<details>" >> "$GITHUB_STEP_SUMMARY"
298-
echo "<summary>What are missed mutants?</summary>" >> "$GITHUB_STEP_SUMMARY"
299-
echo "<br>" >> "$GITHUB_STEP_SUMMARY"
300-
echo "No test failed with this mutation applied, which seems to indicate a gap in test coverage. Or, it may be that the mutant is undistinguishable from the correct code. You may wish to add a better test, or mark that the function should be skipped." >> "$GITHUB_STEP_SUMMARY"
301-
echo "</details>" >> "$GITHUB_STEP_SUMMARY"
302-
echo "" >> "$GITHUB_STEP_SUMMARY"
303-
elif [[ "$section_title" == "Timeout:" ]]; then
304-
echo "<details>" >> "$GITHUB_STEP_SUMMARY"
305-
echo "<summary>What are timeout mutants?</summary>" >> "$GITHUB_STEP_SUMMARY"
306-
echo "<br>" >> "$GITHUB_STEP_SUMMARY"
307-
echo "The mutation caused the test suite to run for a long time, until it was eventually killed. You might want to investigate the cause and potentially mark the function to be skipped." >> "$GITHUB_STEP_SUMMARY"
308-
echo "</details>" >> "$GITHUB_STEP_SUMMARY"
309-
echo "" >> "$GITHUB_STEP_SUMMARY"
310-
elif [[ "$section_title" == "Unviable:" ]]; then
311-
echo "<details>" >> "$GITHUB_STEP_SUMMARY"
312-
echo "<summary>What are unviable mutants?</summary>" >> "$GITHUB_STEP_SUMMARY"
313-
echo "<br>" >> "$GITHUB_STEP_SUMMARY"
314-
echo "The attempted mutation doesn't compile. This is inconclusive about test coverage and no action is needed, unless you wish to test the specific function, in which case you may wish to add a 'Default::default()' implementation for the specific return type." >> "$GITHUB_STEP_SUMMARY"
315-
echo "</details>" >> "$GITHUB_STEP_SUMMARY"
316-
echo "" >> "$GITHUB_STEP_SUMMARY"
317-
fi
318-
319-
if [[ "$section_title" != "" ]]; then
320-
awk -F':' '{printf "- [ ] " "[" $0 "]"; file_path=$1; line=$2; $1=""; $2=""; printf "(" "'"$server_url"'/'"$organisation"'/'"$repository"'/blob/'"$commit"'/" file_path "#L" line-1 ")\n\n"}' "$file_name" >> "$GITHUB_STEP_SUMMARY"
321-
else
322-
awk -F':' '{printf "- [x] " "[" $0 "]"; file_path=$1; line=$2; $1=""; $2=""; printf "(" "'"$server_url"'/'"$organisation"'/'"$repository"'/blob/'"$commit"'/" file_path "#L" line-1 ")\n\n"}' "$file_name" >> "$GITHUB_STEP_SUMMARY"
323-
fi
324-
325-
if [[ "$section_title" == "Missed:" ]]; then
326-
echo "### To resolve this issue, consider one of the following options:" >> "$GITHUB_STEP_SUMMARY"
327-
echo "- Modify or add tests including this function." >> "$GITHUB_STEP_SUMMARY"
328-
echo "- If you are absolutely certain that this function should not undergo mutation testing, add '#[mutants::skip]' or '#[cfg_attr(test, mutants::skip)]' function header to skip it." >> "$GITHUB_STEP_SUMMARY"
329-
elif [[ "$section_title" == "Timeout:" ]]; then
330-
echo "### To resolve this issue, consider one of the following options:" >> "$GITHUB_STEP_SUMMARY"
331-
echo "- Modify the tests that include this funcion." >> "$GITHUB_STEP_SUMMARY"
332-
echo "- Add '#[mutants::skip]' or '#[cfg_attr(test, mutants::skip)]' function header to skip it." >> "$GITHUB_STEP_SUMMARY"
333-
elif [[ "$section_title" == "Unviable:" ]]; then
334-
echo "### To resolve this issue, consider one of the following options:" >> "$GITHUB_STEP_SUMMARY"
335-
echo "- Create 'Default::default()' implementation for the specific structure." >> "$GITHUB_STEP_SUMMARY"
336-
echo "- Add '#[mutants::skip]' or '#[cfg_attr(test, mutants::skip)]' function header to skip it." >> "$GITHUB_STEP_SUMMARY"
337-
fi
338-
339-
echo >> "$GITHUB_STEP_SUMMARY"
340-
fi
341-
}
342-
343-
echo "# Uncaught Mutants" >> "$GITHUB_STEP_SUMMARY"
344-
write_section "Missed:" "./mutants-shards/missed.txt"
345-
write_section "Timeout:" "./mutants-shards/timeout.txt"
346-
write_section "Unviable:" "./mutants-shards/unviable.txt"
347-
348-
echo "# Caught Mutants" >> "$GITHUB_STEP_SUMMARY"
349-
write_section "" "./mutants-shards/caught.txt"
350-
351-
exit_code=$(<"mutants-shards/exit_code.txt")
352-
353-
case $exit_code in
354-
0)
355-
if [[ -f ./mutants-shards/unviable.txt ]]; then
356-
echo "Found unviable mutants!"
357-
exit 1
358-
fi
359-
echo "All new and updated functions are caught!"
360-
;;
361-
1)
362-
echo "Invalid command line arguments!"
363-
exit 1
364-
;;
365-
2 | 3)
366-
echo "Found missed/timeout/unviable mutants!"
367-
exit 1
368-
;;
369-
4)
370-
echo "Building the packages failed without any mutations!"
371-
exit 1
372-
;;
373-
*)
374-
echo "Unknown exit code: $exit_code"
375-
exit 1
376-
;;
377-
esac
133+
- name: Output Mutants
134+
uses: stacks-network/actions/mutation-testing/output-pr-mutants@feat/mutation-testing

0 commit comments

Comments
 (0)