{"id":36790648,"url":"https://github.com/csmith/contempt","last_synced_at":"2026-04-03T12:06:04.304Z","repository":{"id":39876105,"uuid":"420267079","full_name":"csmith/contempt","owner":"csmith","description":"Container file templating","archived":false,"fork":false,"pushed_at":"2025-11-20T14:31:37.000Z","size":235,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-20T16:20:43.021Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/csmith.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-10-22T23:26:45.000Z","updated_at":"2025-11-20T14:31:39.000Z","dependencies_parsed_at":"2025-01-06T20:28:07.955Z","dependency_job_id":"fba5d71c-445b-4b73-8088-bc335a056f22","html_url":"https://github.com/csmith/contempt","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/csmith/contempt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmith%2Fcontempt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmith%2Fcontempt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmith%2Fcontempt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmith%2Fcontempt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/csmith","download_url":"https://codeload.github.com/csmith/contempt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmith%2Fcontempt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28338998,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-01-12T13:25:17.984Z","updated_at":"2026-01-12T13:25:21.248Z","avatar_url":"https://github.com/csmith.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Contempt\n\nNote: this repository currently contains the released version of contempt\nunder `cmd/contempt`, and new work-in-progress commands under\n`cmd/contempt-generator`, `cmd/contempt-writer` and `cmd/contempt-builder`.\nThese new commands are not yet finished, and all the documentation below\nrefers to the old, single command.\n\n---\n\nContempt is a tool to generate Dockerfiles (or Containerfiles) from templates.\n\nIt comes with support for various useful functions for getting the latest versions\nof software, expanding out the dependency trees of package managers, and so on.\n\nThe most basic invocation of contempt takes a source directory and a destination\ndirectory (these can be the same). Within these directories, it is expected that\neach container image is defined in its own subdir, e.g.:\n\n```\ninput\n↳ image1\n  ↳ Dockerfile.gotpl\n  ↳ something-or-other.patch\n↳ image2\n  ↳ Dockerfile.gotpl\n  \noutput\n↳ image1\n  ↳ Dockerfile\n↳ image2\n  ↳ Dockerfile\n```\n\nContempt's job is to take those template files and generate the plain version\nin the output directory:\n\n```shell\ngo install github.com/csmith/contempt/cmd/contempt@latest\ncontempt input_dir output_dir\n```\n\nContempt also has options to make a git commit every time an output file, build\nthe corresponding image using buildah, and push it to a registry:\n\n```shell\ncontempt -commit -build -push . .\n```\n\nYou can also limit contempt to a single project:\n\n```shell\ncontempt -project=image1 . .\n```\n\nOther miscellaneous options are available:\n\n```\nUsage of contempt:\n-alpine-mirror string\n    [ALPINE_MIRROR] Base URL of the Alpine mirror to use to query version and package info (default \"https://dl-cdn.alpinelinux.org/alpine/\")\n-build\n    [BUILD] Whether to automatically build on successful commit\n-commit\n    [COMMIT] Whether to automatically git commit each changed file\n-force-build\n    [FORCE_BUILD] Whether to build projects regardless of changes\n-git-tag-pass string\n    [GIT_TAG_PASS] Password to use when querying git tags\n-git-tag-user string\n    [GIT_TAG_USER] Username to use when querying git tags\n-includes string\n    [INCLUDES] Folder of template files to include (default \"_includes\")\n-output string\n    [OUTPUT] The name of the output files (default \"Dockerfile\")\n-project string\n    [PROJECT] A comma-separated list of projects to generate, instead of all detected ones\n-push\n    [PUSH] Whether to automatically push on successful commit\n-push-retries int\n    [PUSH_RETRIES] How many times to retry pushing an image if it fails (default 2)\n-registry string\n    [REGISTRY] Registry to use for pushes and pulls (default \"reg.c5h.io\")\n-registry-pass string\n    [REGISTRY_PASS] Password to use when querying the container registry\n-registry-user string\n    [REGISTRY_USER] Username to use when querying the container registry\n-source-link string\n    [SOURCE_LINK] Link to a browsable version of the source repo (default \"https://github.com/example/repo/blob/master/\")\n-template string\n    [TEMPLATE] The name of the template files (default \"Dockerfile.gotpl\")\n-workflow-commands\n    [WORKFLOW_COMMANDS] Whether to output GitHub Actions workflow commands to format logs (default true)\n```\n\nIn practice, you will probably want to set the `-registry` and `-source-link` parameters to point\nat the correct place along with the `commit`/`build`/`push` options as required.\n\n## Template functions\n\nContempt uses Go's built-in [text/template](https://golang.org/pkg/text/template/) package,\nand provides the following functions:\n\n### Image\n\n```gotemplate\n{{image \"alpine\"}}\n```\n\nFetches the latest digest for the given image from the configured registry, and returns the fully-qualified\nname with the digest (e.g. `reg.c5h.io/alpine@sha256:abcd...........`).\n\nIf the image name includes a registry, then it is used as-is regardless of the `registry` flag value:\n\n```gotemplate\n{{image \"docker.io/library/hello-world\"}}\n```\n\nNote: see below for information on passing credentials when using more than one registry.\n\n### Registry\n\n```gotemplate\n{{registry}}\n```\n\nReturns the registry configured with the `-registry` flag.\n\n### Alpine release\n\n```gotemplate\n{{alpine_url}}\n{{alpine_checksum}}\n```\n\nReturns the URL and checksum for the latest release of Alpine.\n\n### Golang release\n\n```gotemplate\n{{golang_url}}\n{{golang_checksum}}\n```\n\nReturns the URL and checksum for the latest release of Golang.\n\n### Postgres release\n\n```gotemplate\n# Deprecated - use {{postgres_url 13}} and {{postgres_checksum 13}}\n{{postgres13_url}}\n{{postgres13_checksum}}\n\n# Deprecated - use {{postgres_url 14}} and {{postgres_checksum 14}}\n{{postgres14_url}}\n{{postgres14_checksum}}\n\n# Deprecated - use {{postgres_url 15}} and {{postgres_checksum 15}}\n{{postgres15_url}}\n{{postgres15_checksum}}\n\n# Deprecated - use {{postgres_url 16}} and {{postgres_checksum 16}}\n{{postgres16_url}}\n{{postgres16_checksum}}\n\n# Deprecated - use {{postgres_url 17}} and {{postgres_checksum 17}}\n{{postgres17_url}}\n{{postgres17_checksum}}\n\n{{postgres_url 17}}\n{{postgres_checksum 17}}\n```\n\nReturns the URL and checksum for the latest release of a specific major version of Postgres.\n\n### Alpine packages\n\n```gotemplate\nRUN apk add --no-cache \\\n        {{range $key, $value := alpine_packages \"ca-certificates\" \"musl\" \"tzdata\" \"rsync\" -}}\n        {{$key}}={{$value}} \\\n        {{end}};\n```\n\nGiven one or more Alpine packages, resolves all of their dependencies and returns a flattened\nlist of all packages pinned to their current versions.\n\n### GitHub tag\n\n```gotemplate\n{{github_tag \"csmith/contempt\"}}\n{{prefixed_github_tag \"csmith/contempt\" \"release-\"}}\n```\n\nReturns the latest semver tag of the given repository. The \"prefixed\" variant will discard\nthe given prefix from tag names before comparing them using semver.\n\nUse the `-git-tag-user` and `-git-tag-pass` flags if authentication is required.\n\n### Git tag\n\n```gotemplate\n{{git_tag \"https://git.sr.ht/~csmith/example\"}}\n{{prefixed_git_tag \"https://git.sr.ht/~csmith/example\" \"release-\"}}\n```\n\nReturns the latest semver tag of the given repository. The \"prefixed\" variant will discard\nthe given prefix from tag names before comparing them using semver.\n\nUse the `-git-tag-user` and `-git-tag-pass` flags if authentication is required.\n\n### Regex URL content\n\n```gotemplate\n{{regex_url_content \"google_button\" \"https://www.google.com/\" \"I'm feeling (L[a-z]+)\"}}\n```\n\nRequests the given URL over HTTP and attempts to match the regular expression.\nReturns the text captured by the first capturing group in the regex.\nThe first argument is a friendly name used for logging and BOM tracking.\n\n### Increment int\n\n```gotemplate\n{{increment_int 3}}\n```\n\nReturns the given integer incremented by one.\n\n### Create map\n\n```gotemplate\n{{map \"key1\" 1 \"key2\" .SomeData}}\n```\n\nCreates a map. Argument list must be even, and all keys must be strings.\nUseful for passing data to other templates.\n\n### Create array\n\n```gotemplate\n{{arr \"elem1\" \"elem2\" .SomeData}}\n```\n\nCreates an array (slice). Useful for passing data to other templates.\n\n## Dealing with registry credentials\n\nThere are two cases in which contempt requires credentials: checking the latest digest for an image in a non-public\nregistry (when the `{{image}}` template function is used), and pushing built images (when the `-push` flag is used).\n\n### Checking digests\n\nYou can supply a single set of credentials to use for checking digests using the `-registry-user` and `-registry-pass`\nflags (or associated environment variables). If these options aren't passed and the registry is not public, then\ncredentials will be read from `~/.docker/config.json` if it exists, else `${XDG_RUNTIME_DIR}/containers/auth.json`.\n\n### Pushing\n\nFor pushes, contempt expects `buildah` to handle authentication for it. To that end, you will probably want to call\n`buildah login` before running contempt. Buildah will also read from `~/.docker/config.json` so a `docker login`\nwill also suffice.\n\n### GitHub Actions\n\nIf you are running contempt using GitHub Actions (or possibly other CI tooling) and need to supply multiple sets\nof credentials for the `{{image}}` function, you may encounter a number of inconvenient issues:\n\n- The `XDG_RUNTIME_DIR` env var is not set, and the `/run/user` directory is not writable, meaning `buildah login`\n  stores its credentials in `/var/tmp/containers-user-1001/containers/containers/auth.json`. Contempt will not\n  read from this location when trying to find credentials for the `{{image}}` function.\n- The default actions image comes pre-supplied with a `~/.docker/config.json` with credentials for Docker Hub.\n  Because this file exists contempt won't even attempt to read `${XDG_RUNTIME_DIR}/containers/auth.json`, even\n  if you've set the environment variable to a sensible value.\n\nThe simplest way to deal with this situation is to use `docker login` to write credentials to Docker's config file.\n\n## Example\n\nCheck out [csmith/dockerfiles](https://github.com/csmith/dockerfiles) for a collection of\ntemplates and outputs generated using contempt.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsmith%2Fcontempt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcsmith%2Fcontempt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsmith%2Fcontempt/lists"}