{"id":15517304,"url":"https://github.com/skx/thyme","last_synced_at":"2026-05-05T12:33:39.599Z","repository":{"id":150430526,"uuid":"140943306","full_name":"skx/thyme","owner":"skx","description":"A simple package-building system, using docker","archived":false,"fork":false,"pushed_at":"2018-07-28T18:46:10.000Z","size":48,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T19:50:55.054Z","etag":null,"topics":["automation","ci","debian","docker","pipeline"],"latest_commit_sha":null,"homepage":null,"language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skx.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2018-07-14T12:11:36.000Z","updated_at":"2025-02-10T08:45:40.000Z","dependencies_parsed_at":"2023-04-24T17:27:51.663Z","dependency_job_id":null,"html_url":"https://github.com/skx/thyme","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/skx/thyme","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fthyme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fthyme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fthyme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fthyme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skx","download_url":"https://codeload.github.com/skx/thyme/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fthyme/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32649585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["automation","ci","debian","docker","pipeline"],"created_at":"2024-10-02T10:12:26.126Z","updated_at":"2026-05-05T12:33:39.576Z","avatar_url":"https://github.com/skx.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CI\n\nThere seem to be an explosion of CI/Pipeline tools recently.  I've used a few,\nand I'm watching [ick](https://ick.liw.fi/) with particular interest.\n\nWhile a general-purpose CI system is perhaps overkill for my needs I do\nhave the desire to automate some tasks which run in isolated and transient\ncontainers - and 99% of these tasks are \"build something\".\n\nFor example:\n\n* Build a website, via [templer](http://github.com/skx/templer), [hugo](https://gohugo.io/), or similar tool.\n* Build a debian package.\n\nIn both cases the result will then be uploaded somewhere - for example a website might be pushed to a live location via `rsync`, and a generated Debian binary-package might be uploaded to a package-repository via `dput`.\n\n\n\n## Architecture of a Job\n\nIn my experience the task of running a CI job can be broadly divided into three parts:\n\n* Tasks which are executed (on the host) before we begin.\n  * For example cloning a remote `git` repository.\n  * Running this on the host simplifies things because you don't need to setup an SSH key in the container environment.\n* Tasks that happen in isolation, in a container or transient environment.\n* Tasks which are executed (on the host) after we've finished.\n  * For example uploading the generated result(s) to a remote host.\n  * Again running this step on the host simplifies things because you don't need to setup credentials in your container for carrying out the upload.\n\n\n## CI Job Configuration\n\nWe've established that we probably want to execute the main build inside a\ntransient docker container, and some things outside (typically the \"before\"\nand \"after\" stages).\n\nThis is how `thyme` implements this:\n\n* Create a temporary directory on the host.\n  * Run the \"before\" steps against this temporary directory-tree.\n  * This is probably where you'd clone your remote `git`, `hg`, etc, repository.\n* Bind-mount that into the container in a known-location \"`/work`\".\n  * Run the \"build\" steps inside that container against the repository.\n* Then upload the results.\n  * By running the \"after\" steps on the host.\n\nIn short a job is configured by writing a simple recipe which has three\ndistinct sections within it, each containing shell-commands:\n\n* \"before\"\n  * Runs on the host.\n* \"during\"\n  * Runs in the container.\n* \"after\"\n  * Runs on the host.\n\nEach of these sections is optional, though of course you'll need to add at least\none.  This repository includes some genuine CI recipes here:\n\n* [kpie.recipe](kpie.recipe)\n   * Builds a Debian binary package of the [kpie](https://github.com/skx/kpie) utility.\n* [lumail.recipe](lumail.recipe)\n   * Build a [lumail](https://github.com/lumail/lumail) binary.\n* [failing.recipe](failing.recipe)\n   * Demonstrates that failures terminate the build(s) cleanly.\n\nIt might be that you'd want to run ALL the steps inside a container.  In that\ncase just ignore the `before:` and `after:` sections in your recipe - as this\nexample shows:\n\n* [no-host.recipe](no-host.recipe)\n   * Run all the steps in the container.\n   * We have an `after:` section solely to show it worked.\n\n\n\n## Usage\n\nTo test this out:\n\n* Write a recipe, based upon one of the examples.\n* Invoke `thyme --recipe=/path/to/recipe.file` to run your job.\n* Finally to automate things 100%:\n   * Add a git-hook to make this happen every time you run `git push`!\n\nBy default `thyme` will run using Debian stretch image, but you can specify\na different one upon the command-line, or even in your recipe (as\nthe [kpie.recipe](kpie.recipe) does ):\n\n    $ thyme --recipe ./failing.recipe --container=debian:jessie\n\nvs:\n\n    $ thyme --recipe ./failing.recipe --container=debian:stretch\n\n\n\n\n# HTTP Build-Server\n\nThis repository contains a simple HTTP-server which can be used to\nlist and trigger builds:\n\n    $ go run server.go\n\nOnce launched you'll see a list of all recipes (\u003c*.recipe\u003e) and clicking\non one will trigger the job - the output will be streamed to your client.\n\nThe screen will scroll down to follow new output, until the process has\nterminated.\n\n\n\n# Feedback?\n\nFeedback is welcome.  Of course the thing we're missing from Jenkins\nor Gitlab runners is the notion of dependencies.  Here a job has three\nstages and nothing else.\n\nOf course our three stages might not all be present.\n\nSteve\n--\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskx%2Fthyme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskx%2Fthyme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskx%2Fthyme/lists"}