33 push :
44 pull_request :
55 types : [opened, reopened]
6+ workflow_dispatch :
67jobs :
7- determine_run_parameters :
8- runs-on : ubuntu-24.04
9- outputs :
10- mutant_mode : ${{ steps.set_params.outputs.mutant_mode }}
11- mutant_since_target : ${{ steps.set_params.outputs.mutant_since_target }}
12- num_groups : ${{ steps.set_params.outputs.num_groups }}
13- steps :
14- - name : Determine Mutation Run Parameters
15- id : set_params
16- shell : bash
17- env :
18- EVENT_NAME : ${{ github.event_name }}
19- REF_NAME : ${{ github.ref_name }}
20- PR_BASE_REF : ${{ github.event.pull_request.base.ref }}
21- PR_TITLE : ${{ github.event.pull_request.title }}
22- PR_BODY : ${{ github.event.pull_request.body }}
23- COMMIT_MESSAGES_JOINED_WITH_SPACES_ACTIONS : ${{ join(github.event.commits.*.message, ' ') }}
24- COMMIT_MESSAGES_JOINED_WITH_SLASHES_ACTIONS : ${{ join(github.event.commits.*.message, ' // ') }}
25-
26- run : |
27- echo "--- Debug: Determining mutation run parameters for pricing ---"
28- echo "Event name: $EVENT_NAME"
29- echo "Ref name: $REF_NAME"
30- echo "Base ref (for PR): $PR_BASE_REF"
31- echo "PR title: $PR_TITLE"
32-
33- RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SLASHES="$COMMIT_MESSAGES_JOINED_WITH_SLASHES_ACTIONS"
34- RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SPACES="$COMMIT_MESSAGES_FOR_JOIN_WITH_SPACES_ACTIONS"
35-
36- CLEANED_COMMIT_MESSAGES_FOR_LOG="${RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SLASHES//\'/}"
37- COMMIT_MESSAGES_LOG=$(echo "${CLEANED_COMMIT_MESSAGES_FOR_LOG}" | head -c 500)
38- echo "Commit messages in push (cleaned, first 500 chars): ${COMMIT_MESSAGES_LOG}..."
39-
40- CLEANED_COMMIT_MESSAGES_FOR_CONTAINS="${RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SPACES//\'/}"
41-
42- if [[ "${CLEANED_COMMIT_MESSAGES_FOR_CONTAINS}" == *"[mutate-full]"* ]]; then
43- CONTAINS_MUTATE_FULL_IN_PUSH="true"
44- else
45- CONTAINS_MUTATE_FULL_IN_PUSH="false"
46- fi
47- echo "Contains '[mutate-full]' in push commit messages (from cleaned messages): $CONTAINS_MUTATE_FULL_IN_PUSH"
48-
49- CLEANED_PR_TITLE="${PR_TITLE//\'/}"
50- if [[ "${CLEANED_PR_TITLE}" == *"[mutate-full]"* ]]; then
51- CONTAINS_MUTATE_FULL_IN_PR_TITLE="true"
52- else
53- CONTAINS_MUTATE_FULL_IN_PR_TITLE="false"
54- fi
55- echo "Contains '[mutate-full]' in PR title (from cleaned title): $CONTAINS_MUTATE_FULL_IN_PR_TITLE"
56-
57- CLEANED_PR_BODY="${PR_BODY//\'/}"
58- if [[ "${CLEANED_PR_BODY}" == *"[mutate-full]"* ]]; then
59- CONTAINS_MUTATE_FULL_IN_PR_BODY="true"
60- else
61- CONTAINS_MUTATE_FULL_IN_PR_BODY="false"
62- fi
63- echo "Contains '[mutate-full]' in PR body (from cleaned body): $CONTAINS_MUTATE_FULL_IN_PR_BODY"
64-
65- echo "---------------------------------------------"
66-
67- FINAL_MUTANT_MODE="full"
68- FINAL_NUM_GROUPS=16
69- FINAL_SINCE_TARGET=""
70-
71- IS_MUTATE_FULL_TRIGGERED="false"
72- if [[ "$EVENT_NAME" == "pull_request" && \
73- ( "$CONTAINS_MUTATE_FULL_IN_PR_TITLE" == "true" || "$CONTAINS_MUTATE_FULL_IN_PR_BODY" == "true" ) ]]; then
74- echo "Logic path: [mutate-full] in PR title/body."
75- IS_MUTATE_FULL_TRIGGERED="true"
76- elif [[ "$EVENT_NAME" == "push" && "$CONTAINS_MUTATE_FULL_IN_PUSH" == "true" ]]; then
77- echo "Logic path: [mutate-full] in push commit message(s)."
78- IS_MUTATE_FULL_TRIGGERED="true"
79- fi
80-
81- if [[ "$IS_MUTATE_FULL_TRIGGERED" == "true" ]]; then
82- echo "Action: Mode set to 'full' (NUM_GROUPS=16) due to [mutate-full] trigger."
83- FINAL_MUTANT_MODE="full"
84- FINAL_NUM_GROUPS=16
85- else
86- if [[ "$EVENT_NAME" == "pull_request" ]]; then
87- echo "Logic path: Pull request event (no [mutate-full] trigger)."
88- echo "Action: Mode set to 'incremental' (NUM_GROUPS=2) for PR."
89- FINAL_MUTANT_MODE="incremental"
90- FINAL_NUM_GROUPS=2
91- FINAL_SINCE_TARGET="origin/$PR_BASE_REF"
92- echo "Incremental target: $FINAL_SINCE_TARGET"
93- elif [[ "$EVENT_NAME" == "push" ]]; then
94- if [[ "$REF_NAME" == "master" || "$REF_NAME" == "main" ]]; then
95- echo "Logic path: Push event to main branch (no [mutate-full] trigger)."
96- echo "Action: Mode set to 'full' (NUM_GROUPS=16) for main branch."
97- FINAL_MUTANT_MODE="full"
98- FINAL_NUM_GROUPS=16
99- else
100- echo "Logic path: Push event to non-main branch ('$REF_NAME') (no [mutate-full] trigger)."
101- echo "Action: Mode set to 'incremental' (NUM_GROUPS=2) for branch push."
102- FINAL_MUTANT_MODE="incremental"
103- FINAL_NUM_GROUPS=2
104- FINAL_SINCE_TARGET="origin/master"
105- echo "Incremental target: $FINAL_SINCE_TARGET"
106- fi
107- fi
108- fi
109-
110- echo "Debug before GITHUB_OUTPUT: FINAL_MUTANT_MODE='${FINAL_MUTANT_MODE}'"
111- echo "Debug before GITHUB_OUTPUT: FINAL_SINCE_TARGET='${FINAL_SINCE_TARGET}'"
112- echo "Debug before GITHUB_OUTPUT: FINAL_NUM_GROUPS='${FINAL_NUM_GROUPS}'"
113-
114- echo "mutant_mode=${FINAL_MUTANT_MODE}" >> $GITHUB_OUTPUT
115- echo "mutant_since_target=${FINAL_SINCE_TARGET}" >> $GITHUB_OUTPUT
116- echo "num_groups=${FINAL_NUM_GROUPS}" >> $GITHUB_OUTPUT
117-
118- echo "--- Final Parameters for pricing ---"
119- echo "Mutant Mode: ${FINAL_MUTANT_MODE}"
120- echo "Mutant Since Target: ${FINAL_SINCE_TARGET}"
121- echo "Num Groups: ${FINAL_NUM_GROUPS}"
122- echo "------------------------"
123-
1248 test :
1259 runs-on : ubuntu-24.04
126- strategy :
127- fail-fast : false
128- env :
129- WORKING_DIRECTORY : ecommerce/pricing
130- steps :
131- - uses : actions/checkout@v3
132- - uses : ruby/setup-ruby@v1
133- with :
134- ruby-version : ruby-3.3.7
135- bundler-cache : true
136- working-directory : ${{ env.WORKING_DIRECTORY }}
137- - run : make test
138- working-directory : ${{ env.WORKING_DIRECTORY }}
139- - uses : 8398a7/action-slack@v3
140- with :
141- status : custom
142- fields : workflow,job,commit,repo,ref,author,took
143- custom_payload : |
144- {
145- attachments: [{
146- color: '${{ job.status }}' === 'success' ? 'good' : '${{ job.status }}' === 'failure' ? 'danger' : 'warning',
147- text: `${process.env.AS_WORKFLOW}/${{ github.job }} ${{ job.status }} in ${process.env.AS_TOOK}\n${process.env.AS_COMMIT} in ${process.env.AS_REF} for pricing`,
148- }]
149- }
150- env :
151- SLACK_WEBHOOK_URL : ${{ secrets.CI_WEBHOOK }}
152- if : always()
153- continue-on-error : true
154-
155- prepare_mutation_subjects_pricing :
156- runs-on : ubuntu-24.04
157- needs : determine_run_parameters
158- outputs :
159- subject_groups : ${{ steps.split_subjects.outputs.subject_groups }}
160- env :
161- WORKING_DIRECTORY : ecommerce/pricing
162- steps :
163- - uses : actions/checkout@v3
164- with :
165- fetch-depth : 0
166- - uses : ruby/setup-ruby@v1
167- with :
168- ruby-version : ruby-3.3.7
169- bundler-cache : true
170- working-directory : ${{ env.WORKING_DIRECTORY }}
171- - name : List and split subjects for pricing
172- id : split_subjects
173- working-directory : ${{ env.WORKING_DIRECTORY }}
174- env :
175- NUM_GROUPS_FROM_CI : ${{ needs.determine_run_parameters.outputs.num_groups }}
176- run : |
177- echo "--- Preparing subjects for pricing ---"
178- SUBJECT_LIST_OUTPUT=$(bundle exec mutant environment subject list)
179-
180- mapfile -t subjects_array < <( \
181- echo "$SUBJECT_LIST_OUTPUT" | \
182- awk 'NR == 1 {next} /Run options:/ {exit} {print}' | \
183- sed 's/\x1b\[[0-9;]*m//g' | \
184- sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | \
185- awk 'NF' \
186- )
187-
188- if [ ${#subjects_array[@]} -eq 0 ]; then
189- echo "No subjects found for pricing after cleaning. Setting empty subject_groups."
190- echo "subject_groups=[]" >> $GITHUB_OUTPUT
191- exit 0
192- fi
193-
194- total_subjects=${#subjects_array[@]}
195- NUM_GROUPS=${NUM_GROUPS_FROM_CI:-2}
196- echo "Total subjects found: $total_subjects"
197- echo "Number of parallel groups to create: $NUM_GROUPS"
198- groups_json_array_content=""
199-
200- for (( i=0; i<NUM_GROUPS; i++ )); do
201- current_group_subjects_array=()
202- for (( j=i; j<total_subjects; j+=NUM_GROUPS )); do
203- current_group_subjects_array+=("${subjects_array[j]}")
204- done
205-
206- if [ ${#current_group_subjects_array[@]} -gt 0 ]; then
207- group_subjects_string=$(IFS=' '; echo "${current_group_subjects_array[*]}")
208-
209- if [ -n "$groups_json_array_content" ]; then
210- groups_json_array_content="$groups_json_array_content,"
211- fi
212- escaped_group_subjects_string=$(printf '%s' "$group_subjects_string" | sed 's/"/\\"/g')
213- groups_json_array_content="$groups_json_array_content\"$escaped_group_subjects_string\""
214- fi
215- done
216- echo "Generated subject_groups for pricing: [$groups_json_array_content]"
217- echo "subject_groups=[$groups_json_array_content]" >> $GITHUB_OUTPUT
218- echo "-----------------------------------"
219-
220- mutate :
221- needs : [determine_run_parameters, prepare_mutation_subjects_pricing]
222- if : ${{ needs.prepare_mutation_subjects_pricing.outputs.subject_groups != '[]' && needs.prepare_mutation_subjects_pricing.outputs.subject_groups != '' }}
223- runs-on : ubuntu-24.04
224- strategy :
225- fail-fast : false
226- matrix :
227- subject_group : ${{ fromJson(needs.prepare_mutation_subjects_pricing.outputs.subject_groups) }}
228- env :
229- WORKING_DIRECTORY : ecommerce/pricing
230- MUTANT_MODE : ${{ needs.determine_run_parameters.outputs.mutant_mode }}
231- MUTANT_SINCE_TARGET : ${{ needs.determine_run_parameters.outputs.mutant_since_target }}
23210 steps :
233- - uses : actions/checkout@v3
234- with :
235- fetch-depth : 0
11+ - uses : actions/checkout@v4
23612 - uses : ruby/setup-ruby@v1
23713 with :
23814 ruby-version : ruby-3.3.7
23915 bundler-cache : true
240- working-directory : ${{ env.WORKING_DIRECTORY }}
241- - name : Run mutation tests (parallel group for pricing)
242- run : |
243- echo "Debug from CI step before calling make (using PASSED_ var names):"
244- echo " Value for PASSED_MODE='${{ env.ENV_CLI_MUTANT_MODE }}'"
245- echo " Value for PASSED_SINCE_TARGET='${{ env.ENV_CLI_MUTANT_SINCE_TARGET }}'"
246- echo " CI_MUTATE_SUBJECTS (from env): '${{ env.CI_MUTATE_SUBJECTS }}'"
247-
248- make mutate \
249- PASSED_MODE="${{ env.ENV_CLI_MUTANT_MODE }}" \
250- PASSED_SINCE_TARGET="${{ env.ENV_CLI_MUTANT_SINCE_TARGET }}"
251- working-directory : ${{ env.WORKING_DIRECTORY }}
252- env :
253- CI_MUTATE_SUBJECTS : ${{ matrix.subject_group }}
254-
255- notify_pricing_mutation_summary :
256- runs-on : ubuntu-24.04
257- needs : [mutate, prepare_mutation_subjects_pricing]
258- if : always() && needs.prepare_mutation_subjects_pricing.outputs.subject_groups != '[]' && needs.prepare_mutation_subjects_pricing.outputs.subject_groups != ''
259- steps :
260- - name : Determine notification color
261- id : set_color
262- run : |
263- if [[ "${{ needs.mutate.result }}" == "success" ]]; then
264- echo "NOTIFICATION_COLOR=good" >> $GITHUB_ENV
265- elif [[ "${{ needs.mutate.result }}" == "failure" ]]; then
266- echo "NOTIFICATION_COLOR=danger" >> $GITHUB_ENV
267- else
268- echo "NOTIFICATION_COLOR=warning" >> $GITHUB_ENV
269- fi
270- - name : Send mutation summary notification
271- uses : 8398a7/action-slack@v3
272- with :
273- status : custom
274- fields : workflow,commit,repo,ref,author
275- custom_payload : |
276- {
277- "attachments": [{
278- "color": "${{ env.NOTIFICATION_COLOR }}",
279- "text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|pricing> Mutation Test Summary:\nStatus: ${{ needs.mutate.result }}\nWorkflow: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>\nCommit: <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> in ${{ github.ref }}"
280- }]
281- }
282- env :
283- SLACK_WEBHOOK_URL : ${{ secrets.CI_WEBHOOK }}
16+ working-directory : ecommerce/pricing
17+ - run : make -C ecommerce/pricing test
0 commit comments