{"id":20081967,"url":"https://github.com/exercism/configlet","last_synced_at":"2025-03-02T13:42:16.808Z","repository":{"id":38535463,"uuid":"292409564","full_name":"exercism/configlet","owner":"exercism","description":"The official tool for managing Exercism language track repositories.","archived":false,"fork":false,"pushed_at":"2025-02-01T21:35:41.000Z","size":957,"stargazers_count":23,"open_issues_count":153,"forks_count":14,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-02-23T17:21:32.183Z","etag":null,"topics":["community-contributions-paused"],"latest_commit_sha":null,"homepage":"https://exercism.org/docs/building/configlet","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exercism.png","metadata":{"funding":{"github":["exercism"],"custom":["https://exercism.org/donate"]},"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-02T22:38:39.000Z","updated_at":"2025-02-01T21:35:44.000Z","dependencies_parsed_at":"2024-03-12T02:28:08.071Z","dependency_job_id":"52fc2906-ff01-4a9f-8d1d-2358314ee912","html_url":"https://github.com/exercism/configlet","commit_stats":{"total_commits":606,"total_committers":15,"mean_commits":40.4,"dds":"0.33003300330033003","last_synced_commit":"923e0647b2974fcc38faa849feddd8cd040d0f27"},"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fconfiglet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fconfiglet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fconfiglet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fconfiglet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exercism","download_url":"https://codeload.github.com/exercism/configlet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241515953,"owners_count":19975140,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["community-contributions-paused"],"created_at":"2024-11-13T15:41:09.990Z","updated_at":"2025-03-02T13:42:16.783Z","avatar_url":"https://github.com/exercism.png","language":"Nim","funding_links":["https://github.com/sponsors/exercism","https://exercism.org/donate"],"categories":[],"sub_categories":[],"readme":"# Configlet\n\nThe official tool for managing Exercism language track repositories.\n\n## Download\n\nEach track should have a `bin/fetch-configlet` script, and might have a `bin/fetch-configlet.ps1` script too.\nThe first is a bash script, and the second is a PowerShell script.\n\nRunning one of these scripts downloads the latest version of configlet to the `bin` directory.\nYou can then use configlet by running `bin/configlet`, or `bin/configlet.exe` on Windows.\n\n### Verifying\n\nExercism signs each configlet release archive with [`minisign`](https://jedisct1.github.io/minisign/).\n\nFor now, if you want to verify the signature of a configlet release, you need to do it manually.\nThe `fetch-configlet` script may support checking the release signature in the future, but it won't require checking it: Exercism doesn't want to require every `fetch-configlet` user to install `minisign`.\n\nTo verify a release archive, first download (from the assets section of a [release](https://github.com/exercism/configlet/releases)) the archive and its corresponding `.minisig` file.\nWrite them to the same directory.\nFor example, to verify the configlet `4.0.0-beta.13` Linux x86-64 release, download these files to the same directory:\n\n```text\nconfiglet_4.0.0-beta.13_linux_x86-64.tar.gz\nconfiglet_4.0.0-beta.13_linux_x86-64.tar.gz.minisig\n```\n\nThen run a `minisign` command in that directory:\n\n```shell\nminisign -Vm configlet_4.0.0-beta.13_linux_x86-64.tar.gz -P RWQGj6DTXgYLhKvWJMGtbDUrZerawUcyWnti9MGuWMx7VDW9DqZn2tMZ\n```\n\nwhere the argument to `-P` is the [configlet public key](https://github.com/exercism/configlet/blob/009dc9df9d947e71ff039ac2af0f82315dbf9073/configlet-minisign.pub).\n\nThe preceding command has verified the release archive if (and only if) the command's output begins with `Signature and comment signature verified`.\nFor example:\n\n```text\nSignature and comment signature verified\nTrusted comment: timestamp:2023-08-09T10:27:15Z  file:configlet_4.0.0-beta.13_linux_x86-64.tar.gz  hashed\n```\n\nThen extract the archive to obtain the (now-verified) configlet executable.\nYou may delete the archive and the `.minisig` file.\n\n## Usage\n\nThe application is a single binary, and you can use it as follows:\n\n```text\nUsage:\n  configlet [global-options] \u003ccommand\u003e [command-options]\n\nCommands:\n  completion  Output a completion script for a given shell\n  create      Add a new exercise, approach or article\n  fmt         Format the exercise 'config.json' files\n  generate    Generate Concept Exercise 'introduction.md' files from 'introduction.md.tpl' files\n  info        Print some information about the track\n  lint        Check the track configuration for correctness\n  sync        Check or update Practice Exercise docs, metadata, and tests from 'problem-specifications'.\n              Check or populate missing 'files' values for Concept/Practice Exercises from the track 'config.json'.\n  uuid        Output new (version 4) UUIDs, suitable for the value of a 'uuid' key\n\nOptions for completion:\n  -s, --shell \u003cshell\u003e             Choose the shell type (required)\n                                  Allowed values: b[ash], f[ish], z[sh]\n\nOptions for create:\n      --approach \u003cslug\u003e           The slug of the approach\n      --article \u003cslug\u003e            The slug of the article\n      --practice-exercise \u003cslug\u003e  The slug of the practice exercise\n      --concept-exercise \u003cslug\u003e   The slug of the concept exercise\n  -e, --exercise \u003cslug\u003e           Only operate on this exercise\n  -o, --offline                   Do not update the cached 'problem-specifications' data\n  -a, --author                    The author of the exercise, approach or article\n  -d, --difficulty                The difficulty of the exercise (default: 1)\n\nOptions for fmt:\n  -e, --exercise \u003cslug\u003e           Only operate on this exercise\n  -u, --update                    Prompt to write formatted files\n  -y, --yes                       Auto-confirm the prompt from --update\n\nOptions for generate:\n  -e, --exercise \u003cslug\u003e           Only operate on this exercise\n  -u, --update                    Prompt to write generated files\n  -y, --yes                       Auto-confirm the prompt from --update\n\nOptions for info:\n  -o, --offline                   Do not update the cached 'problem-specifications' data\n\nOptions for sync:\n  -e, --exercise \u003cslug\u003e           Only operate on this exercise\n  -o, --offline                   Do not update the cached 'problem-specifications' data\n  -u, --update                    Prompt to update the unsynced track data\n  -y, --yes                       Auto-confirm prompts from --update for updating docs, filepaths, and metadata\n      --docs                      Sync Practice Exercise '.docs/introduction.md' and '.docs/instructions.md' files\n      --filepaths                 Populate empty 'files' values in Concept/Practice exercise '.meta/config.json' files\n      --metadata                  Sync Practice Exercise '.meta/config.json' metadata values\n      --tests [mode]              Sync Practice Exercise '.meta/tests.toml' files.\n                                  The mode value specifies how missing tests are handled when using --update.\n                                  Allowed values: c[hoose], i[nclude], e[xclude] (default: choose)\n\nOptions for uuid:\n  -n, --num \u003cint\u003e                 Number of UUIDs to output\n\nGlobal options:\n  -h, --help                      Show this help message and exit\n      --version                   Show this tool's version information and exit\n  -t, --track-dir \u003cdir\u003e           Specify a track directory to use instead of the current directory\n  -v, --verbosity \u003cverbosity\u003e     The verbosity of output.\n                                  Allowed values: q[uiet], n[ormal], d[etailed] (default: normal)\n```\n\n## `configlet lint`\n\nThe primary function of configlet is to do _linting_: checking if a track's configuration files are correctly structured - both syntactically and semantically.\nMisconfigured tracks may not sync correctly, may look wrong on the website, or may present a suboptimal user experience.\nConfiglet's checks are therefore important for maintaining the integrity of Exercism.\n\nThe `configlet lint` command is still under development.\nThe list of currently implemented checks is [here](https://github.com/exercism/configlet/issues/249).\n\n## `configlet sync`\n\nA Practice Exercise on an Exercism track is often implemented from a specification in the [`exercism/problem-specifications`](https://github.com/exercism/problem-specifications) repository.\n\nExercism intentionally requires that every exercise has its own copy of certain files (such as `.docs/instructions.md`), even when that exercise exists in `problem-specifications`.\nTherefore configlet has a `sync` command, which can check that such Practice Exercises on a track are in sync with that upstream source, and can update them when updates are available.\n\nThere are three kinds of data that configlet can update from `problem-specifications`: documentation, metadata, and tests.\nThere is also one kind of data that configlet can populate from the track-level `config.json` file: filepaths in exercise config files.\n\nLater sections describe the checking and updating of these data kinds, but as a quick summary:\n\n- `configlet sync` only operates on exercises that exist in the track-level `config.json` file.\n  Therefore if you are implementing a new exercise on a track and want to add the initial files with `configlet sync`, add the exercise to the track-level `config.json` file first.\n  If the exercise isn't yet ready to be user-facing, set its `status` value to `wip`.\n- A plain `configlet sync` makes no changes to the track, and checks every data kind for every exercise.\n- To operate on a subset of data kinds, use some combination of the `--docs`, `--filepaths`, `--metadata`, and `--tests` options.\n- To interactively update data on the track, use the `--update` option.\n- To non-interactively update docs, filepaths, and metadata on the track, use `--update --yes`.\n- To non-interactively include every unseen test for a given exercise, use (for example) `--update --tests include --exercise prime-factors`.\n- To skip downloading the `problem-specifications` repository, add `--offline --prob-specs-dir /path/to/local/problem-specifications`\n- Note that `configlet sync` tries to preserve the key order in exercise `.meta/config.json` files when updating.\n  To write these files in a canonical form without syncing, use the `configlet fmt` command.\n  However, `configlet sync` _does_ add (possibly empty) required keys (`authors`, `files`, `blurb`) when they're missing.\n  This is less like syncing, but more ergonomic: when implementing a new exercise, you can use `sync` to create a starter `.meta/config.json` file.\n- `configlet sync` removes keys that aren't in the spec.\n  Custom key/value pairs are still supported, but you must write them inside a JSON object named `custom`.\n- Configlet exits with an exit code of 0 when all the seen data are up to date, and 1 otherwise.\n\nNote that in `configlet` releases `4.0.0-alpha.34` and earlier, the `sync` command operated only on tests.\n\n### Docs\n\nA Practice Exercise that originates from the `problem-specifications` repository must have a `.docs/instructions.md` file (and possibly a `.docs/introduction.md` file too) containing the exercise documentation from `problem-specifications`.\n\nTo check every Practice Exercise on the track for available documentation updates (exiting with a nonzero exit code if at least one update is available):\n\n```shell\nconfiglet sync --docs\n```\n\nTo interactively update the docs for every Practice Exercise, add the `--update` option (or `-u` for short):\n\n```shell\nconfiglet sync --docs --update\n```\n\nTo non-interactively update the docs for every Practice Exercise, add the `--yes` option (or `-y` for short):\n\n```shell\nconfiglet sync --docs --update --yes\n```\n\nTo operate on a single Practice Exercise, use the `--exercise` option (or `-e` for short).\nFor example, to non-interactively update the docs for the `prime-factors` exercise:\n\n```shell\nconfiglet sync --docs -uy -e prime-factors\n```\n\n### Metadata\n\nEvery exercise on a track must have a `.meta/config.json` file.\nFor a Practice Exercise that originates from the `problem-specifications` repository, this file should contain the `blurb`, `source` and `source_url` key/value pairs that exist in the corresponding upstream `metadata.toml` file.\n\nTo check every Practice Exercise for available metadata updates (exiting with a nonzero exit code if at least one update is available):\n\n```shell\nconfiglet sync --metadata\n```\n\nTo interactively update the metadata for every Practice Exercise, add the `--update` option (or `-u` for short):\n\n```shell\nconfiglet sync --metadata --update\n```\n\nTo non-interactively update the metadata for every Practice Exercise, add the `--yes` option (or `-y` for short):\n\n```shell\nconfiglet sync --metadata --update --yes\n```\n\nTo operate on a single Practice Exercise, use the `--exercise` option (or `-e` for short).\nFor example, to non-interactively update the metadata for the `prime-factors` exercise:\n\n```shell\nconfiglet sync --metadata -uy -e prime-factors\n```\n\n### Tests\n\nIf a track implements an exercise for which test data exists in the [problem-specifications repository](https://github.com/exercism/problem-specifications), the exercise _must_ contain a `.meta/tests.toml` file.\nThe goal of the `tests.toml` file is to track which tests the exercise implements.\nEach test in this file has a UUID to identify it, and may have an `include` key to specify whether the test is implemented.\n\nA `tests.toml` file has this format:\n\n```toml\n# This is an auto-generated file.\n#\n# Regenerating this file via `configlet sync` will:\n# - Recreate every `description` key/value pair\n# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications\n# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)\n# - Preserve any other key/value pair\n#\n# As user-added comments (using the # character) will be removed when this file\n# is regenerated, comments can be added via a `comment` key.\n\n[1e22cceb-c5e4-4562-9afe-aef07ad1eaf4]\ndescription = \"basic\"\n\n[79ae3889-a5c0-4b01-baf0-232d31180c08]\ndescription = \"lowercase words\"\n\n[ec7000a7-3931-4a17-890e-33ca2073a548]\ndescription = \"invalid input\"\ninclude = false\ncomment = \"excluded because we don't want to add error handling to the exercise\"\n```\n\nIn this case, the track has chosen to implement two of the three available tests.\nIf a track uses a _test generator_ to generate an exercise's test suite, it _must_ use the contents of the `tests.toml` file to determine which tests to include in the generated test suite.\n\nTo check every Practice Exercise `tests.toml` file for available tests updates (exiting with a nonzero exit code if there is at least one test case that appears in the exercise's canonical data, but not in the `tests.toml`):\n\n```shell\nconfiglet sync --tests\n```\n\nTo interactively update the `tests.toml` file for every Practice Exercise, add the `--update` option:\n\n```shell\nconfiglet sync --tests --update\n```\n\nFor each missing test, this prompts the user to choose whether to include/exclude/skip it, and updates the corresponding `tests.toml` file as appropriate.\nConfiglet writes an exercise's `tests.toml` file when the user has finished making choices for that exercise.\nThis means that you can exit configlet at a prompt (for example, by pressing Ctrl-C in the terminal) and only lose the syncing decisions for at most one exercise.\n\nTo non-interactively include every unseen test case, use `--tests include`.\nFor example, to do so for an exercise named `prime-factors`:\n\n```shell\nconfiglet sync --tests include -u -e prime-factors\n```\n\nRemember to actually implement these tests on the track.\n\n### Filepaths\n\nFinally, the `sync` command also handles \"syncing\" from a source that isn't `problem-specifications` - the track-level `config.json` file.\nEvery Concept Exercise and Practice Exercise must have a `.meta/config.json` file with a `files` object that specifies the (relative) locations of the files that the exercise uses.\nSuch filepaths usually follow a simple pattern, and so configlet can populate the exercise-level values from patterns in the `files` key of the track-level `config.json` file.\n\nTo check that every Concept Exercise and Practice Exercise on the track has a fully populated `files` key (or at least one that configlet can populate from the track-level `files` key):\n\n```shell\nconfiglet sync --filepaths\n```\n\n(Note that `configlet lint` also produces an error when an exercise has a missing or empty `files` key.)\n\nTo populate empty or missing values of the exercise-level `files` key for every Concept Exercise and Practice Exercise from the patterns in the track-level `files` key:\n\n```shell\nconfiglet sync --filepaths --update\n```\n\nTo do this non-interactively and for a single exercise named `prime-factors`:\n\n```shell\nconfiglet sync --filepaths -uy -e prime-factors\n```\n\n### Using `sync` when adding a new exercise to a track\n\nThe `sync` command is useful when adding a new exercise to a track.\nIf you are adding a Practice Exercise named `foo` that exists in `problem-specifications`, one possible workflow is:\n\n1. Manually add an entry to the track-level `config.json` file for the exercise `foo`.\n   This makes the exercise visible to `configlet sync`.\n1. Run `configlet sync --docs --filepaths --metadata -uy -e foo` to create the exercise's documentation, and a starter `.meta/config.json` file with populated `files`, `blurb`, and perhaps `source` and `source_url` values.\n1. Edit the exercise `.meta/config.json` file as needed.\n   For example, add yourself to the `authors` array.\n1. Run `configlet sync --tests include -u -e foo` to create a `.meta/tests.toml` file with every test included.\n1. View that `.meta/tests.toml` file, and add `include = false` to any test case that the exercise won't implement.\n1. Implement the tests for the exercise to match those included in `.meta/tests.toml`.\n1. Add the other required files.\n\n## `configlet fmt`\n\nAn Exercism track repository has many JSON files, including:\n\n- The track `config.json` file.\n\n- For each concept, a `.meta/config.json` and `links.json` file.\n\n- For each Concept Exercise or Practice Exercise, a `.meta/config.json` file.\n\nThese files are more readable if they have a consistent formatting Exercism-wide, and so configlet has a `fmt` command for rewriting a track's JSON files in a canonical form.\n\nThe `fmt` command currently only operates on the exercise `.meta/config.json` files, but it's likely to operate on all the track JSON files in the future.\n\nA plain `configlet fmt` makes no changes to the track, and checks the formatting of the `.meta/config.json` file for every Concept Exercise and Practice Exercise.\n\nTo print a list of paths for which there isn't already a formatted exercise `.meta/config.json` file (exiting with a nonzero exit code if at least one exercise lacks a formatted config file):\n\n```shell\nconfiglet fmt\n```\n\nTo make configlet prompt to write formatted config files, add the `--update` option (or `-u` for short):\n\n```shell\nconfiglet fmt --update\n```\n\nTo non-interactively write the formatted config files, add the `--yes` option (or `-y` for short):\n\n```shell\nconfiglet fmt --update --yes\n```\n\nTo operate on a single exercise, use the `--exercise` option (or `-e` for short).\nFor example, to non-interactively write the formatted config file for the `prime-factors` exercise:\n\n```shell\nconfiglet fmt -uy -e prime-factors\n```\n\nWhen writing JSON files, `configlet fmt` will:\n\n- Write the key/value pairs in the canonical order.\n\n- Use two spaces for indentation.\n\n- Use a separate line for each item in a JSON array, and each key in a JSON object.\n\n- Remove key/value pairs for keys that are optional and have empty values.\n  For example, it removes `\"source\": \"\"`.\n\n- Remove `\"test_runner\": true` from Practice Exercise config files.\n  This is an optional key - the spec says that an omitted `test_runner` key implies the value `true`.\n\n- When a JSON object has more than one key/value pair with some key name, keep only the final one.\n\nThe canonical key order for an exercise `.meta/config.json` file is:\n\n```text\n- authors\n- [contributors]\n- files\n  - solution\n  - test\n  - exemplar           (Concept Exercises only)\n  - example            (Practice Exercises only)\n  - [editor]\n  - [invalidator]\n- [language_versions]\n- [forked_from]        (Concept Exercises only)\n- [test_runner]        (Practice Exercises only)\n- [representer]\n  - version\n- [icon]\n- blurb\n- [source]\n- [source_url]\n- [custom]\n```\n\nwhere the square brackets indicate that the enclosed key is optional.\n\nNote that `configlet fmt` only operates on exercises that exist in the track-level `config.json` file.\nTherefore if you are implementing a new exercise on a track and want to format its `.meta/config.json` file, add the exercise to the track-level `config.json` file first.\nIf the exercise isn't yet ready to be user-facing, set its `status` value to `wip`.\n\nThe exit code is 0 when every seen exercise has a formatted `.meta/config.json` file when configlet exits, and 1 otherwise.\n\n## `configlet uuid`\n\nEach exercise and concept has a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier), which must only appear once across all of Exercism.\nIt must be a valid version 4 UUID (compliant with RFC 4122) in the canonical textual representation, which means that it must match this regular expression:\n\n```text\n^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$\n```\n\nYou can run `configlet uuid` to output a new, appropriate UUID.\nThere is also the `-n, --num` option for outputting multiple new UUIDs:\n\n```console\n$ configlet uuid --num 5\n3823f890-be49-4700-baac-e19de8fda76f\nc12309a2-8bd6-4b9c-a511-e1ee4083f492\n26167ad5-fe20-43d4-8b1f-3bbb9618c36e\n5df11ac0-e612-4223-b0f8-f6cd2cb15cb1\ne42b94bb-9c90-47f2-aebb-03cdbc27bf3b\n```\n\n## `configlet generate`\n\nEach concept exercise and concept have an `introduction.md` file.\nIf you want the exercise's introduction to include the concept's introduction verbatim, you can create a `introduction.md.tpl` file to achieve this.\nThis file may use a placeholder to refer to the concept's introduction, so that the information isn't duplicated.\n\nConcept placeholders must use the following format:\n\n```text\n%{concept:\u003cslug\u003e}\n```\n\nFor example, if the track has a concept named `floating-point-numbers` then an `introduction.md.tpl` file can contain:\n\n```text\n%{concept:floating-point-numbers}\n```\n\nYou can run `configlet generate` to generate the exercise's `introduction.md` for any exercise that has an `introduction.md.tpl` file.\nThe generated `introduction.md` is identical to the `introduction.md.tpl`, except that configlet replaces concept placeholders with the contents of the concept's `introduction.md` file (minus its top-level heading).\nIn the future, `configlet generate` will also increment the level of other headings by 1 (for example from `## My Heading` to `### My Heading`), but this isn't yet implemented.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at \u003chttps://github.com/exercism/configlet\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexercism%2Fconfiglet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexercism%2Fconfiglet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexercism%2Fconfiglet/lists"}