Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/infra.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
name: infra
on:
workflow_call:
inputs:
app_name:
description: 'The name of the application to deploy'
required: true
type: string
secrets:
AWS_ACCESS_KEY_ID:
required: true
AWS_SECRET_ACCESS_KEY:
required: true
AWS_REGION:
required: true
push:
pull_request:
types: [opened, reopened]
Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/pricing-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: pricing-coverage
on:
workflow_dispatch:
repository_dispatch:
types:
- script
push:
branches:
- master
paths:
- "ecommerce/pricing/Gemfile.lock"
- ".github/workflows/pricing-coverage.yml"
pull_request:
paths:
- "ecommerce/pricing/Gemfile.lock"
- ".github/workflows/pricing-coverage.yml"
schedule:
- cron: '0 17 * * *'
jobs:
test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ecommerce/pricing
- name: Run tests
run: make -C ecommerce/pricing test
mutate:
needs: test
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ecommerce/pricing
- name: Run full mutation testing
run: make -C ecommerce/pricing mutate
33 changes: 33 additions & 0 deletions .github/workflows/pricing-mutate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: pricing-mutate
on:
push:
pull_request:
types: [opened, reopened]
jobs:
test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ecommerce/pricing
- name: Run tests
run: make -C ecommerce/pricing test
mutate:
needs: test
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ecommerce/pricing
- name: Run incremental mutation testing
run: make -C ecommerce/pricing mutate-changes
274 changes: 4 additions & 270 deletions .github/workflows/pricing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,281 +3,15 @@ on:
push:
pull_request:
types: [opened, reopened]
workflow_dispatch:
jobs:
determine_run_parameters:
runs-on: ubuntu-24.04
outputs:
mutant_mode: ${{ steps.set_params.outputs.mutant_mode }}
mutant_since_target: ${{ steps.set_params.outputs.mutant_since_target }}
num_groups: ${{ steps.set_params.outputs.num_groups }}
steps:
- name: Determine Mutation Run Parameters
id: set_params
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
REF_NAME: ${{ github.ref_name }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
COMMIT_MESSAGES_JOINED_WITH_SPACES_ACTIONS: ${{ join(github.event.commits.*.message, ' ') }}
COMMIT_MESSAGES_JOINED_WITH_SLASHES_ACTIONS: ${{ join(github.event.commits.*.message, ' // ') }}

run: |
echo "--- Debug: Determining mutation run parameters for pricing ---"
echo "Event name: $EVENT_NAME"
echo "Ref name: $REF_NAME"
echo "Base ref (for PR): $PR_BASE_REF"
echo "PR title: $PR_TITLE"

RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SLASHES="$COMMIT_MESSAGES_JOINED_WITH_SLASHES_ACTIONS"
RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SPACES="$COMMIT_MESSAGES_FOR_JOIN_WITH_SPACES_ACTIONS"

CLEANED_COMMIT_MESSAGES_FOR_LOG="${RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SLASHES//\'/}"
COMMIT_MESSAGES_LOG=$(echo "${CLEANED_COMMIT_MESSAGES_FOR_LOG}" | head -c 500)
echo "Commit messages in push (cleaned, first 500 chars): ${COMMIT_MESSAGES_LOG}..."

CLEANED_COMMIT_MESSAGES_FOR_CONTAINS="${RAW_COMMIT_MESSAGES_FOR_JOIN_WITH_SPACES//\'/}"

if [[ "${CLEANED_COMMIT_MESSAGES_FOR_CONTAINS}" == *"[mutate-full]"* ]]; then
CONTAINS_MUTATE_FULL_IN_PUSH="true"
else
CONTAINS_MUTATE_FULL_IN_PUSH="false"
fi
echo "Contains '[mutate-full]' in push commit messages (from cleaned messages): $CONTAINS_MUTATE_FULL_IN_PUSH"

CLEANED_PR_TITLE="${PR_TITLE//\'/}"
if [[ "${CLEANED_PR_TITLE}" == *"[mutate-full]"* ]]; then
CONTAINS_MUTATE_FULL_IN_PR_TITLE="true"
else
CONTAINS_MUTATE_FULL_IN_PR_TITLE="false"
fi
echo "Contains '[mutate-full]' in PR title (from cleaned title): $CONTAINS_MUTATE_FULL_IN_PR_TITLE"

CLEANED_PR_BODY="${PR_BODY//\'/}"
if [[ "${CLEANED_PR_BODY}" == *"[mutate-full]"* ]]; then
CONTAINS_MUTATE_FULL_IN_PR_BODY="true"
else
CONTAINS_MUTATE_FULL_IN_PR_BODY="false"
fi
echo "Contains '[mutate-full]' in PR body (from cleaned body): $CONTAINS_MUTATE_FULL_IN_PR_BODY"

echo "---------------------------------------------"

FINAL_MUTANT_MODE="full"
FINAL_NUM_GROUPS=16
FINAL_SINCE_TARGET=""

IS_MUTATE_FULL_TRIGGERED="false"
if [[ "$EVENT_NAME" == "pull_request" && \
( "$CONTAINS_MUTATE_FULL_IN_PR_TITLE" == "true" || "$CONTAINS_MUTATE_FULL_IN_PR_BODY" == "true" ) ]]; then
echo "Logic path: [mutate-full] in PR title/body."
IS_MUTATE_FULL_TRIGGERED="true"
elif [[ "$EVENT_NAME" == "push" && "$CONTAINS_MUTATE_FULL_IN_PUSH" == "true" ]]; then
echo "Logic path: [mutate-full] in push commit message(s)."
IS_MUTATE_FULL_TRIGGERED="true"
fi

if [[ "$IS_MUTATE_FULL_TRIGGERED" == "true" ]]; then
echo "Action: Mode set to 'full' (NUM_GROUPS=16) due to [mutate-full] trigger."
FINAL_MUTANT_MODE="full"
FINAL_NUM_GROUPS=16
else
if [[ "$EVENT_NAME" == "pull_request" ]]; then
echo "Logic path: Pull request event (no [mutate-full] trigger)."
echo "Action: Mode set to 'incremental' (NUM_GROUPS=2) for PR."
FINAL_MUTANT_MODE="incremental"
FINAL_NUM_GROUPS=2
FINAL_SINCE_TARGET="origin/$PR_BASE_REF"
echo "Incremental target: $FINAL_SINCE_TARGET"
elif [[ "$EVENT_NAME" == "push" ]]; then
if [[ "$REF_NAME" == "master" || "$REF_NAME" == "main" ]]; then
echo "Logic path: Push event to main branch (no [mutate-full] trigger)."
echo "Action: Mode set to 'full' (NUM_GROUPS=16) for main branch."
FINAL_MUTANT_MODE="full"
FINAL_NUM_GROUPS=16
else
echo "Logic path: Push event to non-main branch ('$REF_NAME') (no [mutate-full] trigger)."
echo "Action: Mode set to 'incremental' (NUM_GROUPS=2) for branch push."
FINAL_MUTANT_MODE="incremental"
FINAL_NUM_GROUPS=2
FINAL_SINCE_TARGET="origin/master"
echo "Incremental target: $FINAL_SINCE_TARGET"
fi
fi
fi

echo "Debug before GITHUB_OUTPUT: FINAL_MUTANT_MODE='${FINAL_MUTANT_MODE}'"
echo "Debug before GITHUB_OUTPUT: FINAL_SINCE_TARGET='${FINAL_SINCE_TARGET}'"
echo "Debug before GITHUB_OUTPUT: FINAL_NUM_GROUPS='${FINAL_NUM_GROUPS}'"

echo "mutant_mode=${FINAL_MUTANT_MODE}" >> $GITHUB_OUTPUT
echo "mutant_since_target=${FINAL_SINCE_TARGET}" >> $GITHUB_OUTPUT
echo "num_groups=${FINAL_NUM_GROUPS}" >> $GITHUB_OUTPUT

echo "--- Final Parameters for pricing ---"
echo "Mutant Mode: ${FINAL_MUTANT_MODE}"
echo "Mutant Since Target: ${FINAL_SINCE_TARGET}"
echo "Num Groups: ${FINAL_NUM_GROUPS}"
echo "------------------------"

test:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
env:
WORKING_DIRECTORY: ecommerce/pricing
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ${{ env.WORKING_DIRECTORY }}
- run: make test
working-directory: ${{ env.WORKING_DIRECTORY }}
- uses: 8398a7/action-slack@v3
with:
status: custom
fields: workflow,job,commit,repo,ref,author,took
custom_payload: |
{
attachments: [{
color: '${{ job.status }}' === 'success' ? 'good' : '${{ job.status }}' === 'failure' ? 'danger' : 'warning',
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`,
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.CI_WEBHOOK }}
if: always()
continue-on-error: true

prepare_mutation_subjects_pricing:
runs-on: ubuntu-24.04
needs: determine_run_parameters
outputs:
subject_groups: ${{ steps.split_subjects.outputs.subject_groups }}
env:
WORKING_DIRECTORY: ecommerce/pricing
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: List and split subjects for pricing
id: split_subjects
working-directory: ${{ env.WORKING_DIRECTORY }}
env:
NUM_GROUPS_FROM_CI: ${{ needs.determine_run_parameters.outputs.num_groups }}
run: |
echo "--- Preparing subjects for pricing ---"
SUBJECT_LIST_OUTPUT=$(bundle exec mutant environment subject list)

mapfile -t subjects_array < <( \
echo "$SUBJECT_LIST_OUTPUT" | \
awk 'NR == 1 {next} /Run options:/ {exit} {print}' | \
sed 's/\x1b\[[0-9;]*m//g' | \
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | \
awk 'NF' \
)

if [ ${#subjects_array[@]} -eq 0 ]; then
echo "No subjects found for pricing after cleaning. Setting empty subject_groups."
echo "subject_groups=[]" >> $GITHUB_OUTPUT
exit 0
fi

total_subjects=${#subjects_array[@]}
NUM_GROUPS=${NUM_GROUPS_FROM_CI:-2}
echo "Total subjects found: $total_subjects"
echo "Number of parallel groups to create: $NUM_GROUPS"
groups_json_array_content=""

for (( i=0; i<NUM_GROUPS; i++ )); do
current_group_subjects_array=()
for (( j=i; j<total_subjects; j+=NUM_GROUPS )); do
current_group_subjects_array+=("${subjects_array[j]}")
done

if [ ${#current_group_subjects_array[@]} -gt 0 ]; then
group_subjects_string=$(IFS=' '; echo "${current_group_subjects_array[*]}")

if [ -n "$groups_json_array_content" ]; then
groups_json_array_content="$groups_json_array_content,"
fi
escaped_group_subjects_string=$(printf '%s' "$group_subjects_string" | sed 's/"/\\"/g')
groups_json_array_content="$groups_json_array_content\"$escaped_group_subjects_string\""
fi
done
echo "Generated subject_groups for pricing: [$groups_json_array_content]"
echo "subject_groups=[$groups_json_array_content]" >> $GITHUB_OUTPUT
echo "-----------------------------------"

mutate:
needs: [determine_run_parameters, prepare_mutation_subjects_pricing]
if: ${{ needs.prepare_mutation_subjects_pricing.outputs.subject_groups != '[]' && needs.prepare_mutation_subjects_pricing.outputs.subject_groups != '' }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
subject_group: ${{ fromJson(needs.prepare_mutation_subjects_pricing.outputs.subject_groups) }}
env:
WORKING_DIRECTORY: ecommerce/pricing
MUTANT_MODE: ${{ needs.determine_run_parameters.outputs.mutant_mode }}
MUTANT_SINCE_TARGET: ${{ needs.determine_run_parameters.outputs.mutant_since_target }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby-3.3.7
bundler-cache: true
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Run mutation tests (parallel group for pricing)
run: |
echo "Debug from CI step before calling make (using PASSED_ var names):"
echo " Value for PASSED_MODE='${{ env.ENV_CLI_MUTANT_MODE }}'"
echo " Value for PASSED_SINCE_TARGET='${{ env.ENV_CLI_MUTANT_SINCE_TARGET }}'"
echo " CI_MUTATE_SUBJECTS (from env): '${{ env.CI_MUTATE_SUBJECTS }}'"

make mutate \
PASSED_MODE="${{ env.ENV_CLI_MUTANT_MODE }}" \
PASSED_SINCE_TARGET="${{ env.ENV_CLI_MUTANT_SINCE_TARGET }}"
working-directory: ${{ env.WORKING_DIRECTORY }}
env:
CI_MUTATE_SUBJECTS: ${{ matrix.subject_group }}

notify_pricing_mutation_summary:
runs-on: ubuntu-24.04
needs: [mutate, prepare_mutation_subjects_pricing]
if: always() && needs.prepare_mutation_subjects_pricing.outputs.subject_groups != '[]' && needs.prepare_mutation_subjects_pricing.outputs.subject_groups != ''
steps:
- name: Determine notification color
id: set_color
run: |
if [[ "${{ needs.mutate.result }}" == "success" ]]; then
echo "NOTIFICATION_COLOR=good" >> $GITHUB_ENV
elif [[ "${{ needs.mutate.result }}" == "failure" ]]; then
echo "NOTIFICATION_COLOR=danger" >> $GITHUB_ENV
else
echo "NOTIFICATION_COLOR=warning" >> $GITHUB_ENV
fi
- name: Send mutation summary notification
uses: 8398a7/action-slack@v3
with:
status: custom
fields: workflow,commit,repo,ref,author
custom_payload: |
{
"attachments": [{
"color": "${{ env.NOTIFICATION_COLOR }}",
"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 }}"
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.CI_WEBHOOK }}
working-directory: ecommerce/pricing
- run: make -C ecommerce/pricing test
Loading