πŸŽ’ CLI to create starters from repos + Templates πŸ€– + Actions πŸš€

Overview


Backpack

A tool to curate and automate your starter projects

Key Features β€’ How To Use β€’ Download β€’ Contributing β€’ License

screenshot

Key Features

  • Generate from full project, subfolders, branches, tags 🌠 - use complete, versions, or any parts of repos you like
  • Shortcuts πŸš€ - create a personal or team list of your projects with global and local shortcuts
  • Variable replacements - replace variables in content and path (like cookiecutter)
  • Automated setup steps πŸ€– - run yarn install or make automatically after a clone
  • Interactive inputs - define steps to take inputs and select options in YAML while generating a new project
  • Fast & efficient πŸƒ - no history or .git folder, local caching of content by default, supporting git and tar.gz download

How to Use

$ bp --help
backpack 2.0.0
Set up projects and download files from existing repos

USAGE:
    bp [OPTIONS] [ARGS] [SUBCOMMAND]

ARGS:
    <shortlink>    A full or short link to a repo (e.g. org/user)
    <dest>         Target folder

OPTIONS:
    -c, --config <config>    Use a specified configuration file
    -f, --fetch              Fetch and apply into the current folder
    -g, --git                Clone with git
    -h, --help               Print help information
    -n, --no-cache           Fetch resources without using the cache
    -V, --version            Print version information
    -w, --overwrite          Always overwrite target file(s)

SUBCOMMANDS:
    add       Save a repo as a project
    cache     Cache handling
    config    Create a personal configuration
    help      Print this message or the help of the given subcommand(s)

To download and generate a new project, you can use any repo:

$ bp your/repo

Download

For macOS:

brew tap rusty-ferris-club/tap && brew install backpack

Otherwise, grab a release from releases and run bp --help:

πŸ”¨ Create starters from ordinary repos

Go to your ordinary repo and follow the add wizard:

$ cd your-repo
$ bp add

Note that if a repo contains a .backpack-project.yaml file, it will be automatically used. A .backpack-project.yaml file is a way for the repo author to give instructions for how to make a template out of their project, here's an example:

project:
  shortlink: kriasoft/react-starter-kit
  actions:
  - name: "name of file"
    hook: before
    interaction:
      kind: input
      prompt: name of your app
      out: file_name
  swaps:
  - key: README.md
    val_template: "{{file_name}}"
    path: .*
  - key: tsconfig.json
    val: ts-config.json

You create this file and format in your own repos to make them backpack friendly.

πŸ”¨ Create starters manually

Create a backpack.yaml:

$ bp config --init
wrote: /Users/jondot/.backpack/backpack.yaml.

Configure a starter:

projects:
  rust-starter: 
    shortlink: jondot/rust-starter  # you can use any custom prefix here too
    # is_git: true # force fetch from ssh
    actions:
    - name: run an initial build
      run: cargo build

And now run:

$ bp rust-starter

To personalize a project you can take input and replace content:

projects:
  rust-starter: 
    shortlink: jondot/rust-starter  # you can use any custom prefix here too
    actions:
    - name: get app name
      hook: before
      interaction:
        kind: input
        prompt: name of your app
        out: app_name
    swaps:
    - key: APP_NAME
      val_template: "Welcome to {{app_name}}"
      path: "README.md"

Example of a fully personalize config in my ~/.backpack/backpack.yaml, with minimal prompts (generating from rust-starter):

Show example
projects:
  jondot-rs:
    shortlink: rusty-ferris-club/rust-starter
    actions:
      - name: project
        interaction:
          kind: input
          prompt: project name (e.g. newtool)
          out: project
        hook: before
      - name: description
        interaction:
          kind: input
          prompt: description (e.g. one liner)
          out: description
        hook: before
    swaps:
      - key: __V_PROJECT_NAME__
        val_template: "{{project}}"
        path: ".*"
      - key: __V_REPO_NAME__
        val_template: "jondot/{{project}}"
        path: ".*"
      - key: __V_REPO_URL__
        val_template: "https://github.com/jondot/{{project}}"
        path: ".*"
      - key: __V_PROJECT_FORMULA__
        val_template: "{{project | capitalize}}"
        path: ".*"
      - key: __V_TAP_NAME__
        val: "jondot/homebrew-tap"
        path: ".*"
      - key: __V_BIN_NAME__
        val_template: "{{project}}"
        path: ".*"
      - key: __v_bin_name__
        val_template: "{{project}}"
        path: ".*"
      - key: __V_AUTHOR__
        val: "[email protected]"
        path: ".*"
      - key: __V_DESCRIPTION__
        val_template: "{{description}}"
        path: ".*"

πŸ™‹β€β™€οΈ Configure user projects

bp (with no args) will automatically display a list of projects if configure those.

Projects define repos and custom actions and / or swaps you want to attach to each.

Generate a global user configuration file:

$ bp config --init --global

Edit the file:

$ vim ~/.backpack/backpack.yaml

Add to the projects section:

projects:
  rust-starter: 
    shortlink: rusty-ferris-club/rust-starter

🚨 Run actions and user input

You can add custom actions to a project:

projects:
  rust:
    shortlink: rusty-ferris-club/rust-starter
    actions:
    - name: 🚨 ====== init git ===========
      run: git init . && git add . && git commit -am "first commit"
    - name: 🚨 ====== first build ========
      run: cargo build

You can also add inputs, selections and confirmation, including variable capture.

Show full example
actions:
  - name: "Install deps"
    interaction:
      kind: confirm
      prompt: "are you sure?"
    run: yarn install
    ignore_exit: true
  - name: select a DB
    interaction:
      kind: select
      prompt: select a database
      options:
      - sqlite
      - postgres
      - mysql
      default: sqlite
      out: db
  - name: "generate a model"
    interaction:
      kind: input
      prompt: name of your app?
      out: name
    run: yarn run init-app {{db}} {{name}}

Actions have a before and after hook, which make them run before copying content (e.g. user input), and after the content have being copied (e.g. installing dependencies).

By default actions are hooked to the after event, but you can change it:

- name: name
  hook: before
  interaction:
    kind: input
    prompt: name of your project
    out: project_name

πŸ’‘ Replace content

Define keys to swap, where a key can be anything.

  • Swaps can happen both in content or path.
  • You can limit to a path with a regex
  • You can use a val_template which pulls a variable from those you gathered while running actions. You also have a set of inflections such as {{project_name | kebab_case}}
Show example
projects:
  my-project:
    shortlink: kriasoft/react-starter-kit
    swaps:
    - key: MIT
      val: Apache 2.0
      path: README.md
    - key: AUTHOR_NAME
      val_template: Dr. {{user_name}}
      path: src/.*

FAQ

How can I set up an enterprise / hosted git, or use Gitlab or others? You can use custom git vendors.

Start by generating a configuration file:

$ bp config --init

Example: configure a Github Enterprise instance:

vendors:
  custom:
    ghe: # <--- this prefix is yours
      kind: github
      base: enterprise-github.acme.org
             # `---- it will point here now

And now, you can use the ghe: prefix for your shortlinks:

$ bp ghe:user/repo
What's the difference between `bp` and `bp -f`?
$ bp kriasoft/react-starter-kit my-react-project
$ bp -f kriasoft/react-starter-kit/-/.github

Let's say you really like how react-starter-kit configured its Github Action, and you'd like to copy that to your existing project. You can do this:

  • Use /-/ to access a subfolder
  • Use -f to overlay files onto your current working directory
Can I generate a project without typing the name of the repo?
$ bp

And follow the interactive menu, which will let you:

  • Pick a project, if you have any configured
  • Input a shortlink
  • Input a destination or pick an auto generated one
What's a shortlink?

A shortlink is a pointer to a Git repo which looks like this:

shortlink

Any one of these is a legal shortlink:

user/repo -> resolves to https://github.com/user/repo
gl:user/repo -> resolves to https://gitlab.org/user/repo
user/repo/-/subfolder -> takes only 'subfolder'
user/repo#wip -> takes the 'wip' branch

βœ… Bare minimum is user/repo which defaults to Github.
βœ… You can set up a custom prefix if you want.

Is it possible to use backpack only on parts of source repos?

Yes, use the folder notation /-/:

$ bp user/repo/-/path/to/folder dest-folder
Can I generate from a given branch?

Branches or tags can be used with the #branch specifier.

$ bp kriasoft/react-starter-kit#feature/redux my-starter
Can I use backpack on empty or populated directories?

Yes. Use -f to grab content and apply it to an existing empty or populated directories:

$ cd your-directory
$ bp -f user/repo
Can backpack work on self hosted Git servers?

If it's one of the supported vendors, you can create a custom prefix configuration:

vendors:
  custom:
    gh:
      kind: github
      base: github.acme.com/my-org

Note that in addition to the custom hosted github.acme.com server, we also specified a default org my-org above, so it saves a bit of typing. Then you can run:

$ bp gh:my-repo my-repo
Can backpack infer the name of the destination folder and save me some more typing?

Where it's non ambiguous, yes. For example, when you specify a subfolder:

$ bp user/repo/-/my-folder

Will grab just my-folder from user/repo and create in a destinaton folder called my-folder.

If there's a inference strategy you think will work, open an issue or submit a PR.

How to install backpack globally?

With Homebrew it happens automatically. Otherwise, download a binary and add its containing folder to your PATH in the way that's supported by your OS.

We're accepting PRs for other OS specific installers.

Any requirements or dependencies for backpack?

Just git to exist (and we will eventually remove that dependency). Other than that the bp binary is self contained and has no dependencies.

Can I get a single file?

Yes. backpack will act differently when the source is a file, it will do what you're expecting it to.

For example, this will give you a .gitignore file from another project:

$ cd my-project
$ bp -f rusty-ferris-club/backpack/-/.gitignore
$ tree
.gitignore

This will copy just a single workflow file, but also the entire hierarchy of folders:

$ cd my-project
$ bp -f rusty-ferris-club/backpack/-/.github/workflows/build.yml
$ tree
.github/
  workflows/
    build.yml

Or in other words:

  1. When you specify a target file verbatim, it will use that
  2. If you're not specifying a target file, the destination file and folder path will be copied from the source.

Contributing

We are accepting PRs. Feel free to submit PRs.

To all Contributors - you make this happen, thanks!

License

Copyright (c) 2022 @jondot. See LICENSE for further details.

You might also like...
A CLI tool to get help with CLI tools πŸ™
A CLI tool to get help with CLI tools πŸ™

A CLI tool to get help with CLI tools πŸ™ halp aims to help find the correct arguments for command-line tools by checking the predefined list of common

 create and test the style and formatting of text in your terminal applications
create and test the style and formatting of text in your terminal applications

description: create and test the style and formatting of text in your terminal applications docs: https://docs.rs/termstyle termstyle is a library tha

mdBook is a utility to create modern online books from Markdown files.

Create book from markdown files. Like Gitbook but implemented in Rust

An open source artifact manager. Written in Rust back end and an Vue front end to create a fast and modern experience

nitro_repo Nitro Repo is an open source free artifact manager. Written with a Rust back end and a Vue front end to create a fast and modern experience

Tool to create web interfaces to command-line tools

webgate This command line utility allows you to: serve files and directories listed in a config file remotely run shell commands listed in a config fi

This repo contains crates that are used to create the micro services and keep shared code in a common place.

MyEmma Helper Crates This repo contains crates that can are reused over different services. These crate are used in projects at MyEmma. But these crat

Create tasks and save notes offline from your terminal

Create tasks and save notes offline from your terminal

A Rust-based shell script to create a folder structure to use for a single class every semester. Mostly an excuse to use Rust.

A Rust Course Folder Shell Script PROJECT IN PROGRESS (Spring 2022) When completed, script will create a folder structure of the following schema: [ro

A Command-line tool to create, manage and deploy your python projects

PPM A Command-line tool to create, manage and deploy your python projects Table of Contents PPM Main Features Create a Project project.ini file Projec

Comments
  • external aliases, rename to 'projects'

    external aliases, rename to 'projects'

    Suggestion / Feature Request

    Goal: NOTE aliases now renamed to projects. Allow me to "tap" into external sources for projects so I can just run bp new rust and that gives me the best Rust starter there is, without me having to search for that, configure it etc. In principle similar to formula and Homebrew taps. This shift the focus from me writing my own aliases (projects) to consuming something that's ready-made and public. External file content is the same format of configuration, but we only take projects: for now.

    Design:

    projects_sources:
    - name: community
      link: https://<raw file>
    projects: # previously: aliases
    
    • Config does merging of local and global as before. Now additional step will be added:
    await config.resolve_projects() // mut
    

    Which will:

    1. verify files in ~/.backpack don't already exist. if they do, bail.
    2. if no files corresponding to sources, download the files, name them according to project source name (e.g. community.yaml).

    Next,

    • with the array of external projects,
    • concat all additional projects into projects list in config, only add missing, never overwrite, make sure their source is external
    • resolve from main projects array.

    Some changes to project alias records:

    1. Each alias should now have a source: local | external
    2. Should have a description
    3. Should have a run command (for post-clone). External run will be prompted by user to approve. Local runs will run without prompt.

    The data structure should also support:

    backpack new
    <interactive menu - choose your project>
    

    And should be ready for but not implement yet:

    • fuzzy search in menu

    • frecency score (most recent and most used projects at the top)

    • [ ] rename aliases to projects

    • [ ] project should now have description, run: <string> (not implemented yet), source (default local)

    • [ ] build external projects resolver, returns a list of projects, initialized with external

    • [ ] merge logic in Config, careful not to overwrite from external

    • [ ] Config gets a new defensive API that hides the data inside of it.

    • [ ] new interactive UI module.

    • [ ] implement choice menu, sourced by projects, divided by local and external, rig it to bp new and bp apply when called with no arguments, this also means we will need to take in dest interactively.

    • [ ] bp config --projects should now show a divided list of available projects. consider just saying bp projects instead.

    enhancement 
    opened by jondot 0
  • evaluate replacing current caching library

    evaluate replacing current caching library

    Suggestion / Feature Request

    The current caching library works well and was very easy to use: https://github.com/rusty-ferris-club/backpack/blob/master/backpack/src/fetch.rs#L48

    It is used in a forced way where the cache is kept static for a fixed amount of time. However a smarter strategy would be to:

    1. Have a short-lived cache with no network request (e.g. 1 day)
    2. When (1) expires, perform a cheap Etag/HEAD request to see if anything changed, and expire the cache if needed
    3. After a rather long period of time (e.g. 14 days) expire the cache in any case

    Note:

    We fetch content through git and through HTTP.

    • HTTP has natural caching facilities that can be used
    • see what's the best way to cache around git

    This issue is for evaluation, so a good completion would be to just summarize your findings. A great completion of it would be a working implementation of a new cache mechanism.

    enhancement good first issue 
    opened by jondot 0
  • experiment: move from git bin to libgit

    experiment: move from git bin to libgit

    • can only work for ls-remote (implemented here)
    • there's no support in libgit2 for shallow clone, and it's not getting there for the last few years (PRs exist, but no action), so it means we have to stay with the git binary anyways.
    opened by jondot 0
Releases(v2.1.1)
Owner
Rusty Ferris Club
A builders club for people who love building stuff in Rust. We're also helping and teaching each other.
Rusty Ferris Club
GitHub CLI extension to search some repos interactively.

gh activity GitHub CLI extension to search some repos interactively. It's wrapper to build gh command provided by GitHub CLI, it could search more eas

taka naoga 3 Jul 28, 2023
Create `.gitignore` files using one or more templates from TopTal, GitHub or your own collection

gitnr A cross-platform CLI utility to create .gitignore files using templates. Use templates from the GitHub & TopTal collections Use local files and

reemus.dev 25 Sep 2, 2023
SKYULL is a command-line interface (CLI) in development that creates REST API project structure templates with the aim of making it easy and fast to start a new project.

SKYULL is a command-line interface (CLI) in development that creates REST API project structure templates with the aim of making it easy and fast to start a new project. With just a few primary configurations, such as project name, you can get started quickly.

Gabriel Michaliszen 4 May 9, 2023
YAML(ish) - Terminal UI framework based on templates focused on simplicity

A YAML(ish) based terminal GUI framework for- and by Rust, focussed on making it quick and easy to create a functional UI for an app or game. Based on Crossterm and inspired by Kivy.

null 27 Dec 18, 2022
Core Fiberplane data models and methods for transforming them (templates, providers, markdown conversion)

fiberplane This repository is a monorepo for Rust code that is used throughout Fiberplane's product. Overview base64uuid - A utility for working with

Fiberplane 18 Feb 22, 2023
tmplt is a command-line interface tool that allows you to quickly and easily set up project templates for various programming languages and frameworks

tmplt A User Friendly CLI Tool For Creating New Projects With Templates About tmplt is a command-line tool that lets users quickly create new projects

Humble Penguin 35 Apr 8, 2023
A CLI tool that allow you to create a temporary new rust project using cargo with already installed dependencies

cargo-temp A CLI tool that allow you to create a new rust project in a temporary directory with already installed dependencies. Install Requires Rust

Yohan Boogaert 61 Oct 31, 2022
Simple CLI to (add, delete, update, create) i18n translation file πŸ”€ πŸ¦€

, Inrs Simple CLI to (add, delete, update, create) i18n translation file Copyright (C) 2020-2022 TheAwiteb https://github.com/TheAwiteb/inrs This pr

TheAwiteb 4 Oct 4, 2022
CLI tool to quickly create React + Typescript + Tailwind projects

QUICK INIT CLI Tool to quickly create React projects with Tailwind automatically configured for use. Typescript is selected as default. If JS is to be

Oscar 5 Nov 3, 2022
A simple CLI tool to create python project file structure, written in Rust

Ezpie Create python projects blazingly fast What Ezpie can do? It can create a python project directory What kind of directory can Ezpie create? For c

Faseeh 3 Sep 29, 2023