diff --git a/.github/workflows/sorted.yml b/.github/workflows/sorted.yml new file mode 100644 index 0000000..8ce3103 --- /dev/null +++ b/.github/workflows/sorted.yml @@ -0,0 +1,42 @@ +name: Check practice exercises are sorted + +on: + workflow_call: + inputs: + ordering: + description: "How exercises are ordered" + required: true + type: string + +jobs: + check: + name: Check exercises + runs-on: ubuntu-slim + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - name: Check if practice exercises are sorted + env: + ORDERING: ${{ inputs.ordering }} + run: | + diff <( jq -r '.exercises.practice[].slug' config.json ) <( + jq -r ' + # Bucket by displayed difficulty. 0-3: easy; 4-7: medium; 8-10: hard. + def bucket(i): [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3][i]; + + # Code injection to inject the sort literal expression. + def sort: sort_by('"$ORDERING"'); + + .exercises.practice | + # Add displayed difficulty + map(.bucket = bucket(.difficulty)) | + # Add lowercase name + map(.lowercase_name = (.name | ascii_downcase)) | + # Leave hello-world at the top + if .[0].slug == "hello-world" then + [.[0]] + (.[1:] | sort) + else + sort + end | + map(.slug)[] + ' config.json) diff --git a/README.md b/README.md index f542064..815a195 100644 --- a/README.md +++ b/README.md @@ -295,5 +295,53 @@ jobs: uses: exercism/github-actions/.github/workflows/labels.yml@main ``` +## Reusable workflow: sorted + +The `sorted` reusable workflow checks if the practice exercises on a track are sorted. + +### Extra fields + +Some extra fields are added to the exercise data for sorting. + +* `bucket` is added, which indicates the difficulty "bucket" or "displayed" difficulty (easy, medium, hard). +* `lowercase_name` is added to allow sorting by exercise name, case insensitive. + +### Inputs + +The workflow takes a single input, `ordering` (required), that determines how sorting works. +The `ordering` input is passed to `sort_by()` and must be a valid JQ path expression. + +Some valid ordering values: + +* **".name"**: sort alphabetically by the displayed name +* **".lowercase_name"**: sort alphabetically (case insensitive) by the displayed name +* **".slug"**: sort alphabetically by the slug +* **".bucket"**: sort by the difficulty bucket (easy, medium, hard) +* **".bucket, .slug"**: sort by the difficulty bucket then by slug +* **".difficulty"**: sort by the difficulty value (1, 2, 3, ... 10) +* **".difficulty, .name"**: sort by the difficulty then by name +* **".difficulty, .slug"**: sort by the difficulty then by slug + +### Example + +```yaml +name: Exercise order + +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + call-gha-workflow: + name: check + uses: exercism/github-actions/.github/workflows/sorted.yml@main + with: + ordering: ".bucket, .slug" +``` + [configlet]: https://exercism.org/docs/building/configlet [configlet-lint]: https://exercism.org/docs/building/configlet/lint