{"id":15748052,"url":"https://github.com/binaryphile/jiff","last_synced_at":"2025-07-04T06:04:32.808Z","repository":{"id":143324963,"uuid":"50308253","full_name":"binaryphile/jiff","owner":"binaryphile","description":"System Configuration Task Automation","archived":false,"fork":false,"pushed_at":"2017-10-12T20:23:56.000Z","size":95,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-06T11:28:01.068Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/binaryphile/jiff","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/binaryphile.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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":"2016-01-24T21:06:41.000Z","updated_at":"2018-07-09T21:41:53.000Z","dependencies_parsed_at":"2023-05-30T04:15:30.519Z","dependency_job_id":null,"html_url":"https://github.com/binaryphile/jiff","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fjiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fjiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fjiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fjiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/binaryphile","download_url":"https://codeload.github.com/binaryphile/jiff/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246429448,"owners_count":20775805,"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":[],"created_at":"2024-10-04T05:40:28.511Z","updated_at":"2025-03-31T06:42:29.914Z","avatar_url":"https://github.com/binaryphile.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Jiff\n\n[Jiff] is an automation notebook.  Jiff helps you turn your command-line\nsystem configuration rituals into simple tasks, available wherever you\nneed them.\n\nJiff makes available a command, \"jiff\", which allows you to create\nsubcommands called tasks (e.g. \"jiff mytask\").  Jiff makes it simple to\ncreate new tasks by providing a basic script template that also pulls in\nyour bash history, so you can capture whatever it is you just finished\nworking on.\n\nJiff tasks are not limited to scripts.  They can be any executable,\nalthough it is tailored for scripting.\n\n## Motivation\n\nJiff's goal is to make it possible to create system-independent\nconfiguration scripts without needing complex logic to deal with the\ndifferences in environments.\n\nIf you work on a lot of systems, scripts work fine so long as you have\nmultiple similar machines.  As soon as you introduce new platforms or\nenvironment constraints, they break however.\n\nFor example, scripts written for Red Hat Linux won't work on Ubuntu and\nvice-versa.  Scripts written for servers may not work on desktops.  Some\nsystems may use different commands, or call software packages by\ndifferent names.  Others may be subject to constraints such as firewalls\nwhich don't allow access to the usual download sites.\n\nJiff calls these factors which prevent reusability \"contexts\".\n\n## Strategy\n\nOne way scripts can handle such contextual differences is to add\ncomplexity.  Logic can be introduced to detect and accommodate the\ndifferences in environment.  Gradually scripts becomes more general at\nthe expense of complexity and maintainability.\n\nJiff takes a different approach.  Rather than try to make \"one script to\nrule\" the different environments, it instead makes it easy to write\nscripts which only need to worry about one environment.  It does so by\npulling a switcheroo.  It lets you create multiple versions of the same\nscript under the same name...one for each context.  When you switch\ncontexts, it makes the proper version available automatically.\n\nIf your script only has to deal with its own context, the more it looks\nlike the steps you would take by hand on the command line.  In fact,\nthey can be exactly that simple.  That's why I call jiff a notebook...\nit basically takes notes on what you've done and makes them available as\ntasks.  What jiff adds is automatic organization and availability by\ncontext.\n\n## Contexts\n\nBy default, jiff stores your tasks in a directory that specifies most of\nthe things which might keep it from running elsewhere.  That includes:\n\n- a name chosen by you to describe the context, e.g. \"work\" or \"home\"\n- the detected OS distribution on which you are running, e.g. \"centos-6\"\n  or \"ubuntu-15\"\n- the role that you have on that machine, e.g. \"admin\" or \"user\"\n\nYou can define contexts with any name you like, and you can also nest\nthem with \"/\", e.g. \"work\" and \"work/vagrant\".  You can also define new\nroles, although \"admin\" and \"user\" tend to capture most needs.  Jiff\ndefaults to the \"admin\" role since it is mostly meant to be used for\nsystem administration.\n\nWhen you install jiff on another system, you only need to configure the\ncontext name.  If the rest of the environment matches the original one\n(role and distro), then your original jiff tasks become available.\n\nThe nice thing is that when you're in a new context, you have carte\nblanche to write a new script for a task of the same name.  Just do what\nyou would normally do in the new environment, then capture it as a task.\n\n## System/Context Independence\n\nAs your task library grows, it becomes multiplatform as you implement\nthe same task for multiple contexts.\n\nIn many cases, you'll just want to record your manual steps from each\nenvironment.  If you're inclined to write a single script which handles\nmore than one context, jiff also offers sensible means for reusing code\nand promoting tasks to be available across contexts.  Jiff can also\noverride a more-general task with a specific one tailored for a one-off\ncontext.\n\nThe end result is simplicity for you.  For example, on any system I can\nrun \"jiff install git\" and I will get the latest version of git\ninstalled, independent of:\n\n- whether or not it is in the package repositories\n- which dependencies are required to compile it from source\n- whether I have access to the source download site\n- the package management command syntax\n- whether I am a system admin (global install) or a regular user (local\n  install)\n\n## System Configuration Automation\n\nOnce your system configuration tasks handle all of your contexts, you\ncan build system configuration scripts with them.  This allows you to\nspecify your configuration in an entirely system-independent manner,\nconstructed of jiff tasks.  Much like [Ansible] or [SaltStack] allow you\nto do, but tailored to the way you already do things, in shell, without\nhaving to learn how to do it \"their way\".\n\n## Other Features\n\nThat's the core idea of jiff, but it has other features to make life\neasier as well.  Jiff allows you to deploy your tasks to other machines\nsimply.  It allows you to stay up-to-date with changes in the jiff-core\nproject without having to perform git merges (usually), despite being a\nfork.  And it allows you to sensibly build abstraction into your tasks\nwhenever you like, without forcing you to do so.\n\n## Support\n\nJiff currently has explicit support for Ubuntu 14, 15, CentOS 6 and Red\nHat 6, although it will work on any standard unix which supports\nsymlinks.\n\n## Dependencies\n\nJiff requires a github account and git.  It also requires you to fork\nthis repository, which the installer does automatically.\n\nJiff is implemented in bash, which must be installed on your system.  It\nalso requires Python 2.\n\nJiff supports any shell environment, but requires your initialization\nscripts (bashrc et. al.) to load it onto your path.  The installer does\nthis automatically for bash but not the others at the moment.  If you\nuse fish, zsh or the like, you will need to follow the [basher]\ninstructions for configuring your initialization scripts.  Once basher\nis available on your path, jiff is automatically available as well.\n\n## Installation\n\nUser-land install (no sudo necessary):\n\n    curl -sL https://raw.githubusercontent.com/binaryphile/jiff/master/install-jiff | bash\n\nNOTE: you will be prompted to fork this repository to your github\naccount!  The script will do this for you, but you will be running your\nown copy of the jiff repo.\n\nAlong with creating your new jiff repo, it will install [basher] in the\nuser's home directory, as well as add both jiff and basher to the path.\n\nThere currently is no global system installer.\n\n## Tasks\n\nJiff comes with just the functionality necessary to manage itself.\nYou're expected to provide scripts for what you want it to automate.\n\nJiff's bread and butter are called tasks, which are simply scripts (or\neven programs) you create with a special name.  Each script is then\naccessible as a subcommand to jiff, e.g.:\n\n    jiff my_new_task\n\nJiff will invoke the new task you have created and pass it your\narguments as if you had run the script directly yourself.\n\nWhile this is a good start, it's not very useful yet out of the box.\nThe rest is up to you.  You'll need to know a little bit about how jiff\nworks to make it work for you.\n\n## An Example\n\nI've just installed jiff on my home system.  Since I'm running fish as\nmy shell, I've updated my `config.fish` file to put jiff on my path.  I\nre-enter my shell, or source `config.fish`, to make jiff available.\n\nThe first thing I do is create a context:\n\n```\n\u003e jiff context add home\n```\n\nand check it with:\n\n```\n\u003e jiff context\nUsage: jiff context CONTEXT|none [rhel-6|centos-6|ubuntu-14|ubuntu-15]\n\nAvailable contexts:\n\nhome\n\nCurrently using: home\n```\n\nI could have also run `jiff status`, which tells me my role as well as\ncontext.  The role task also tells you your role:\n\n```\n\u003e jiff role\nUsage: jiff role ROLE\n\nAvailable roles:\n\nadmin\nuser\n\nCurrently using: admin\n```\n\nNow let's do some work.  I want to install mysql and my standard\nconfiguration:\n\n```\n\u003e sudo apt-get install mysql-server \u003e/dev/null\n\u003e curl -sL https://raw.githubusercontent.com/binaryphile/mysql/master/my.cnf | sudo tee /etc/my.cnf\n\u003e sudo service mysql start\n```\n\nNow let's turn this into a task.  Jiff has a convenience syntax for\ninstallation tasks which we'll take advantage of:\n\n```\n\u003e jiff task add mysql-install\n```\n\nThis fires up the editor with the task template and includes the last\nfifty lines of bash history for good measure.  I scrap most of the\ntemplate and leaving the lines above, then save and exit.\n\nJiff's builtin \"install\" task looks for any task with the \"-install\"\nsuffix which matches the named package, and executes that.  So the\nfollowing will run the task we just created:\n\n```\n\u003e jiff install mysql\n```\n\nOtherwise, \"jiff install [package]\" runs the appropriate system package\nmanager to install the named package, e.g. `sudo apt-get install -y\n[package]`.\n\nThe \"-install\" naming scheme allows you to override and extend that\nbehavior with your own script, as we've just done.\n\nFinally, let's push the new task up to our jiff repo:\n\n```\njiff task publish mysql-install\n```\n\n## TODO\n\nSome of this isn't done yet.\n\n- deploy and update jiff remotely\n- automatic context detection\n- dependency specification in task headers\n- polish and trim\n\n## References\n\nIf you're interested in system configuration automation and/or bash\nscripting, here are some resources which inspired jiff:\n\n- [ansible]\n- [basher]\n- [chef]\n- [fucking_shell_scripts]\n- [puppet]\n- [rake]\n- [saltStack]\n- [sub]\n\n[jiff]: https://github.com/binaryphile/jiff\n[git]: https://git-scm.com/\n[rake]: http://docs.seattlerb.org/rake/\n[ansible]: http://www.ansible.com/\n[puppet]: https://puppetlabs.com/\n[chef]: https://www.chef.io/\n[saltstack]: https://saltstack.com/\n[fucking_shell_scripts]: https://github.com/brandonhilkert/fucking_shell_scripts\n[basher]: https://github.com/basherpm/basher\n[sub]: https://github.com/basecamp/sub\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinaryphile%2Fjiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinaryphile%2Fjiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinaryphile%2Fjiff/lists"}