{"id":22525048,"url":"https://github.com/andrewpillar/config","last_synced_at":"2025-10-04T23:11:25.872Z","repository":{"id":57656799,"uuid":"456229581","full_name":"andrewpillar/config","owner":"andrewpillar","description":"A library for working with structured configuration in Go","archived":false,"fork":false,"pushed_at":"2023-03-23T20:51:23.000Z","size":134,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-03T21:40:44.672Z","etag":null,"topics":["configuration-language","go"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrewpillar.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-06T18:01:18.000Z","updated_at":"2024-10-06T17:23:45.000Z","dependencies_parsed_at":"2024-06-21T17:51:27.545Z","dependency_job_id":"2047446e-2799-4bab-b561-6c93449b2cc5","html_url":"https://github.com/andrewpillar/config","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/andrewpillar/config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewpillar%2Fconfig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewpillar%2Fconfig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewpillar%2Fconfig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewpillar%2Fconfig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrewpillar","download_url":"https://codeload.github.com/andrewpillar/config/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewpillar%2Fconfig/sbom","scorecard":{"id":193928,"data":{"date":"2025-08-11","repo":{"name":"github.com/andrewpillar/config","commit":"857da6243cc90477a3efb57e794c7d616c6baa6f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-16T21:25:03.879Z","repository_id":57656799,"created_at":"2025-08-16T21:25:03.879Z","updated_at":"2025-08-16T21:25:03.879Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278386130,"owners_count":25978113,"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","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["configuration-language","go"],"created_at":"2024-12-07T06:08:04.969Z","updated_at":"2025-10-04T23:11:25.818Z","avatar_url":"https://github.com/andrewpillar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Config\n\n* [Overview](#overview)\n* [Options](#options)\n  * [Error handling](#error-handling)\n  * [Environment variables](#environment-variables)\n  * [Custom variable expansion](#custom-variable-expansion)\n  * [Includes](#includes)\n* [Struct tags](#struct-tags)\n* [Syntax](#syntax)\n  * [Comments](#comments)\n  * [String](#string)\n  * [Number](#number)\n  * [Bool](#bool)\n  * [Duration](#duration)\n  * [Size](#size)\n  * [Array](#array)\n  * [Block](#block)\n  * [Label](#label)\n\nConfig is a library for working with structured configuration files in Go. This\nlibrary defines its own minimal structured configuration language.\n\n## Overview\n\nThe language organizes configuration into a list of parameters. Below is an\nexample,\n\n    # Example configuration file.\n\n    net {\n        listen \":https\"\n\n        tls {\n            cert \"/var/lib/ssl/server.crt\"\n            key  \"/var/lib/ssl/server.key\"\n\n            ciphers [\"AES-128SHA256\", \"AES-256SHA256\"]\n        }\n    }\n\n    log access {\n        level \"info\"\n        file  \"/var/log/http/access.log\"\n    }\n\n    body_limt 50MB\n\n    timeout {\n        read  10m\n        write 10m\n    }\n\nThe above file would then be decoded like so in your Go program,\n\n    package main\n\n    import (\n        \"fmt\"\n        \"os\"\n        \"time\"\n\n        \"github.com/andrewpillar/config\"\n    )\n\n    type Config struct {\n        Net struct {\n            Listen string\n\n            TLS struct {\n                Cert    string\n                Key     string\n                Ciphers []string\n            }\n        }\n\n        Log map[string]struct {\n            Level string\n            File  string\n       }\n\n        BodyLimit int64 `config:\"body_limit\"`\n\n        Timeout struct {\n            Read  time.Duration\n            Write time.Duration\n        }\n    }\n\n    func main() {\n        var cfg Config\n\n        if err := config.DecodeFile(\u0026cfg, \"server.conf\"); err != nil {\n            fmt.Fprintf(os.Stderr, \"%s: %s\\n\", os.Args[0], err)\n            os.Exit(1)\n        }\n    }\n\n## Options\n\nOptions can be used to configure how a file is decoded. These are callbacks that\ncan be passed to either the `NewDecoder` function or the `DecodeFile` function.\n\n### Error handling\n\nA custom error handler can be configured via the `ErrorHandler` option. This\ntakes a `func(pos Pos, msg string)` callback, which is called when an error\noccurs during parsing of a file. This is given the position at which the error\noccurred, and the message. If no handler is configured, then the `Stderrh`\nerror handler is used by default.\n\n    config.DecodeFile(\u0026cfg, \"file.conf\", config.ErrorHandler(customHandler))\n\n### Environment variables\n\nEnvironment variables can be supported via the `Envvars` option. This will\nexpand any `${VARIABLE}` that is found in a string literal in the configuration\nfile into the respective environment variable.\n\n    config.DecodeFile(\u0026cfg, \"file.conf\", config.Envvars)\n\nEnvironment variables can also be referenced with the `env` prefix, should you\nrefer more explicitness in your configuration files,\n\n    password \"${env:PASSWORD}\"\n\n### Custom variable expansion\n\nAs previously demonstrated, by default any `${VARIABLE}` that is found in a\nstring literal will be expanded into the resective environment variable. Custom\nvariable expansion can be implemented via the `Expand` option, whereby you\nregister an expansion function against a prefix, for example,\n\n    expandSecret := func(key string) (string, error) {\n        // Assume we have some kind of secret store, Vault, a keystore of some\n        // kind, etc.\n        return secretStore.Get(key)\n    }\n\n    config.DecodeFile(\u0026cfg, \"file.confg\", config.Expand(\"secret\", expandSecret))\n\nin the configuration file we can then use the prefix of `secret` to tell the\ndecoder from where the variable should be taken for expansion,\n\n    password \"${secret:PASSWORD}\"\n\n### Includes\n\nIncludes can be configured via the `Includes` option. This will support the\ninclusion of configuration files via the `include` parameter.\n\n    config.DecodeFile(\u0026cfg, \"file.conf\", config.Includes)\n\n\nThis expects to be given either a string literal or an array of string literals\nfor the file(s) to include,\n\n    include \"database.conf\"\n\n    include [\n        \"database.conf\",\n        \"smtp.conf\",\n    ]\n\n## Struct tags\n\nThe decoding of each parameter can be configured via the `config` struct field\ntag. The name of the tag specifies the parameter to map the field to, and the\nsubsequent comma separated list are additional options.\n\nThe `deprecated` option marks a field as deprecated. This will emit an error\nto the error handler during decoding if the deprecated parameter is encountered.\nFor example, assume you have an `ssl` configuration block that you want to\ndeprecate, you would do the following,\n\n    type TLSConfig struct {\n        CA   string\n        Cert string\n        Key  string\n    }\n\n    type Config struct {\n        TLS TLSConfig\n        SSL TLSConfig `config:\"ssl,deprecated\"`\n    }\n\nto specify the parameter that should replace the `ssl` parameter you would\nseparate the name with a `:` in the option,\n\n    type Config struct {\n        TLS TLSConfig\n        SSL TLSConfig `config:\"ssl,deprecated:tls\"`\n    }\n\nThe `nogroup` option prevents the grouping of labelled parameters into a map.\nThis would be used in an instance where you want more explicit control over\nhow labelled parameters are decoded. For example, consider the following\nconfiguration,\n\n    store sftp {\n        addr \"sftp.example.com\"\n\n        auth {\n            username \"sftp\"\n            identity \"/var/lib/ssh/id_rsa\"\n        }\n    }\n\n    store disk {\n        path \"/var/lib/files\"\n    }\n\nthis defines two `store` blocks that are labelled. Both blocks vary with the\nparameters that they offer. We can decode the above into the below struct,\n\n    type Config struct {\n        Store struct {\n            SFTP struct {\n                Addr string\n\n                Auth struct {\n                    Username string\n                    Identity string\n                }\n            }\n\n            Disk struct {\n                Path string\n            }\n        } `config:\",nogroup\"`\n    }\n\n## Syntax\n\nA configuration file is a plain text file with a list of parameters and their\nvalues. The value of a parameter can either be a literal, array, or a parameter\nblock. Typically, the filename should be suffixed with the `.conf` file\nextension.\n\n### Comments\n\nComments start with `#` and end with a newline. This can either be on a full\nline, or inlined.\n\n    # Full-line comment.\n    temp 0.5 # Inline comment.\n\n### String\n\nA string is a sequence of bytes wrapped between a pair of `\"`. As of now, string\nliterals are limited in their capability. \n\n    string  \"this is a string literal\"\n    string2 \"this is another \\\"string\\\" literal, with escapes\"\n\n### Number\n\nIntegers and floats are supported. Integers are decoded into the `int64` type,\nand floats into the `float64` type.\n\n    int   10\n    float 10.25\n\n### Bool\n\nA bool is a `true` or `false` value.\n\n    bool  true\n    bool2 false\n\n### Duration\n\nDuration is a duration of time. This is a number literal suffixed with either\n`s`, `m`, or `h`, for second, minute, or hour respectively. Duration is decoded\ninto the `time.Duration` type.\n\n    seconds 10s\n    minutes 10m\n    hours   10h\n\nThe duration units can also be combined for more explicit values,\n\n    hour_half 1h30m\n\n### Size\n\nSize is the amount of bytes. This is a number literal suffixed with the unit,\neither `B`, `KB`, `MB`, `GB`, or `TB`. Size is decoded into the `int64` type.\n\n    byte     1B\n    kilobyte 1KB\n    megabyte 1MB\n    gigabyte 1GB\n    terabyte 1TB\n\n### Array\n\nAn array is a list of values, these can either be literals, or blocks wrapped\nin a pair of `[ ]`. Arrays are decoded into a slice of the respective type.\n\n    strings [\"str\", \"str2\", \"str3\"]\n    numbers [1, 2, 3, 4]\n\n    arrays [\n        [1, 2, 3],\n        [4, 5, 6],\n        [7, 8, 9],\n    ]\n\n    blocks [{\n        x 1\n        y 2\n        z 3\n    }, {\n        x 4\n        y 5\n        z 6\n    }, {\n        x 7\n        y 8\n        z 9\n    ]]\n\n### Block\n\nA block is a list of parameters wrapped between a pair of `{ }`. Blocks are\ndecoded into a struct.\n\n    block {\n        param \"value\"\n\n        block2 {\n            param 10\n        }\n    }\n\n### Label\n\nA label can be used to distinguish between parameters of the same name. This\ncan be useful when you have similar configuration parameters that you want to\ndistinguish between. A labelled parameter is decoded into a map, where the\nkey of the map is a string, the label itself, and the value of the map is\nthe type for the parameter. This is not the case if the `nogroup` parameter is\nspecified, in which case the label itself will be mapped to a field in a struct.\n\n    auth ldap {\n        addr \"ldap://example.com\"\n\n        tls {\n            cert \"/var/lib/ssl/client.crt\"\n            key  \"/var/lib/ssl/client.key\"\n        }\n    }\n\n    auth saml {\n        addr \"https://idp.example.com\"\n\n        tls {\n            ca \"/var/lib/ssl/ca.crt\"\n        }\n    }\n\nLabels aren't just limited to blocks, they can be applied to any other\nparameter type,\n\n    ports open [\"8080\", \"8443\"]\n\n    ports close [\"80\", \"443\"]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewpillar%2Fconfig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrewpillar%2Fconfig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewpillar%2Fconfig/lists"}