{"id":22374841,"url":"https://github.com/qubitproducts/bapistrano","last_synced_at":"2025-07-30T22:31:18.537Z","repository":{"id":9073129,"uuid":"58238578","full_name":"QubitProducts/bapistrano","owner":"QubitProducts","description":"Deploy JS apps to s3 multiverse.","archived":false,"fork":false,"pushed_at":"2023-07-11T01:29:47.000Z","size":551,"stargazers_count":9,"open_issues_count":12,"forks_count":1,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-07-29T11:59:06.043Z","etag":null,"topics":["ceh","implement"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/QubitProducts.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}},"created_at":"2016-05-06T22:41:31.000Z","updated_at":"2023-06-02T12:06:11.000Z","dependencies_parsed_at":"2023-02-13T21:16:55.423Z","dependency_job_id":null,"html_url":"https://github.com/QubitProducts/bapistrano","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/QubitProducts/bapistrano","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QubitProducts%2Fbapistrano","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QubitProducts%2Fbapistrano/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QubitProducts%2Fbapistrano/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QubitProducts%2Fbapistrano/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/QubitProducts","download_url":"https://codeload.github.com/QubitProducts/bapistrano/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QubitProducts%2Fbapistrano/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267953590,"owners_count":24171419,"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-07-30T02:00:09.044Z","response_time":70,"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":["ceh","implement"],"created_at":"2024-12-04T21:18:41.629Z","updated_at":"2025-07-30T22:31:18.229Z","avatar_url":"https://github.com/QubitProducts.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bapistrano\n\nAn opinionated way of deploying JS apps to s3.\n\nBap is designed to be easily hooked up with a Continuous Deployment system that would keep all branches always built and uploaded to s3.\n\n## Installation\n\n    $ npm install --save-dev bapistrano\n\n## Usage\n\nTypical usage is\n\n    $ bap release\n\nThis will build, upload and release your project. However, you can get more control by combining the following 2 commands\n\n    $ bap upload\n    $ bap release\n\nFor release branches - upload command only uploads the code without updating the `current` pointer. For feature branches - upload command uploads the code *and* updates the `current` pointer. The reasoning here is that in your CI configuration, you only need to specify `bap upload` to get continuous releases of all your branches, with the exception that the release branches only get uploaded, but not released. This way, if you then execute `bap release` at a later time (to a chat bot or in your terminal) - the release will be instant, since `bap upload` has already been executed in the background by CI.\n\n## All Commands\n\nBuild and upload the current branch. Uploading doesn't affect the `current` pointer.\n\n    $ bap upload\n    $ bap upload --as-branch master\n\nUpdate the `current` pointer of current branch to the latest commit of current branch.\n\n    $ bap release\n    $ bap release --as-branch master\n\nRollback the current release of current branch to the previous release.\n\n    $ bap rollback\n    $ bap rollback --forward\n    $ bap rollback --as-branch master\n\nList all deployments.\n    \n    $ bap list\n    $ bap list --limit 100\n    $ bap list master\n\n## Config\n\nYour aws credentials will be read from ~/.aws or environment variables (this is using [s3fs](https://www.npmjs.com/package/s3fs) under the hood which is using [aws-sdk](https://www.npmjs.com/package/aws-sdk)).\n\nYou can specify bapistrano configuration in `package.json`:\n\n```js\n{\n  \"bap\": {\n    \"bucket\": \"ui\",\n    \"region\": \"eu-west-1\",       # default is us-west-1\n    \"distDir\": \"build\",          # default is `.`\n    \"uploadTo\": \"ui/app\",        # default is package.json#name\n    \"build\": false,              # default is \"npm run build\"\n    \"clean\": false,              # default is \"npm run clean\"\n    \"notify\": 'make slack',      # default is false\n    \"keepReleases\": 5,           # default is -1, which keeps all releases\n    \"keepUploads\": 5,            # default is 5\n    \"private\": [\"*.js.map\"],     # default is [], which means make all files public\n    \"releaseBranches\": [         # default is [\"master\"]\n      \"master\",\n      \"next\"\n    ]\n  }\n}\n```\n\n## What does this do exactly?\n\nBap considers there to be two types of branches. Release branches and feature branches. The default release branch is `master`, but you could set it to `[\"stable\"]` or `[\"master\", \"beta\", \"alpha\"]` or `[\"master\", \"next\"]`. All branches that are not release branches are considered to be feature branches.\n\nConsider you have the following release branches - master and next, and the following feature branches - fix-bug, improve-search. After executing `bap release` in each branch, the structure that `bap` would create on s3 would look something like this:\n\n```\n  bap-bucket\n    app-name\n      master\n        current # file containing 2016-05-06T225500-commit4\n        releases\n          2016-04-05T225500-commit1\n          2016-05-06T225500-commit4\n        uploads\n          2016-04-05T225500-commit1\n          2016-05-06T225500-commit3\n          2016-05-06T225500-commit4\n      next\n        current # file containing 2016-05-17T225500-commit7\n        releases\n          2016-04-15T225500-commit3\n          2016-05-15T225500-commit7\n          2016-05-17T225500-commit8\n        uploads\n          2016-04-15T225500-commit3\n          2016-05-15T225500-commit5\n          2016-05-15T225500-commit7\n          2016-05-17T225500-commit8\n          2016-05-17T225500-commit9\n      fix-bug\n        current # file containing 2016-05-18T225500-commit10\n        releases\n          2016-05-18T225500-commit10\n      improve-search\n        current # file containing 2016-05-18T225500-commit12\n        releases\n          2016-05-18T225500-commit12\n```\n\nBap has 3 commands for deploying `upload`, `release` and `rollback`.\n\n- `upload` - runs `npm run build`, uploads the contents of the project to s3. For feature branches, it directly uploads the release to `releases` directory, immediately updates the `current` pointer and cleans up. For release branches, it only uploads the code to `uploads` directory and doesn't touch the `releases` dir.\n- `release` - updates the `current` pointer to the latest commit of the current branch. In case the commit in question is not uploaded to s3, `upload` is executed first. Typically, if you're previously executed the `upload` task, release will be very quick as it only copies the right release from `uploads` into `releases` and updates the `current` pointer without having to run the build again.\n- `rollback` - updates `current` pointer to point to the previous release. Use `--forward` to update it to the next release. Or specify the release id as an argument to roll to a specific release.\n\nBap has some helper commands for performing chores on s3 `list` and `remove`.\n\n- `list` - lists all deployments of all branches\n- `remove` - removes a deployment specified by a commit or deployment directory. Bap will refuse to remove releases that are pointed at by `current`.\n\n#### Build\n\nBy default, the build command is `npm run build`, but you can specify a custom command in `package.json` key `bap.build`. Similarly, at the end of the `upload` or `release` execution, `npm run clean` gets run. Change this with `bap.clean`. Environment variables BAP_RELEASE_ID and BAP_BRANCH are set before executing the build command so that the build process could take this into account. For example, this might be useful when specifying the `webpack` `publicPath` option. BAP_RELEASE_ID is of structure YYYY-MM-DDTHHmmss-commit, where commit is the first 7 commit characters.\n\n#### REVISION\n\nWhen an upload is succesfully completed, a `REVISION` file gets created in the release dir. You can check for this file to know if the upload is complete.\n\n#### Private / Public\n\nClientside assets are usually meant to be public, say if you want to serve them via Cloudfront CDN. Bapistrano by default makes all uploaded files public.\n\nIf you prefer keeping all assets private, use:\n\n    \"private\": [\"*\"]\n\nIf you want to exlude specific files from being public, use:\n\n    \"private\": [\"*.js.map\", \"manifest.json\"]\n\nPattern matching is done using [minimatch](https://github.com/isaacs/minimatch) with `matchBase: true`.\n\n## Embedding bapistrano assets\n\nOnce the assets are released to s3, the recommended way to embed them into your html is by using Cloudfront CDN in front of the s3 bucket. `Bapistrano` comes with a few helpers for retrieving metadata about the releases. E.g.\n\n```js\nvar bapistrano = require('bapistrano')\n\nvar bap = bapistrano.meta({\n  bucket: 'ui',\n  accessKeyId: '...',\n  secretAccessKey: '...',\n  cache: 60 * 1000\n})\n\nmodule.exports = async function getBundleUrl () {\n  var branch = 'master'\n  var releaseId = await bap.getCurrent('my-app', branch)\n  return `http://d111111abcdef8.cloudfront.net/my-app/${branch}/${releaseId}/bundle.js`\n}\n```\n\n### bapistrano.meta(options)\n\nCreates a meta service that can retrieve current release id and a list of branches.\n\n```js\nbapistrano.meta({\n  bucket: 'ui',\n  region: 'eu-west-1',\n  accessKeyId: '...',\n  secretAccessKey: '...',\n  cache: 60 * 1000 // how long to cache the values for before refetching from s3\n})\n```\n\n### meta.getCurrent(path, branchName)\n\nGet the current release id for the given branch. Returns a release id such as `2016-04-05T225500-commit1`.\n\n```js\nmeta.getCurrent('my-app', 'master')\nmeta.getCurrent('some/subpath/my-app', 'next') // note that first argument is path corresponding to uploadTo setting used when uploading the assets\n```\n\nReturns `null` if the branch does not exist.\n\n### meta.getBranches(path)\n\nGet a list of available branches.\n\n```js\nmeta.getBranches('my-app')\nmeta.getBranches('some/subpath/my-app')\n```\n\nReturns a list of branches such as:\n\n```js\n[{\n  name: 'master',\n  current: '2016-04-05T225500-commit1',\n  released: '2016-04-07T10:02:15.000Z',\n  uploaded: '2016-04-05T22:55:00.000Z'\n}]\n```\n\n## Convention vs Configuration\n\nBapistrano is designed to be easily specialised for your projects without having to repeat the configuration in all of the projects. Say you have 5 projects that you want to deploy with bapistrano and they all live in the same s3 bucket with the same structure and have the same lifecycle commands.\n\nYou can create your own tiny npm package with `bin/bap` that creates a version of bap with custom defaults, e.g.:\n\n```js\n#!/usr/bin/env node\n\nvar path = require('path')\nvar meta = require(path.join(process.cwd(), 'package.json'))\n\nrequire('bapistrano/lib/bin')(Object.assign(require('bapistrano/lib/defaults')(), {\n  bucket: 'all-my-apps',\n  region: 'eu-west-1',\n  uploadTo: 'deployments/' + meta.name,\n  build: 'make build',\n  clean: 'make clean',\n  notify: 'make post-to-slack \u0026\u0026 curl -X POST https://myapp.com'\n}, meta.bap))\n```\n\nNow all 5 of those projects can just call `bap upload` or `bap release` without any further configuration in package.json\n\n## Contributing\n\nRight now there are no automated tests other than linting.\n\nRun linting with\n\n    npm test\n\nRun the manual test with\n\n    cd tests/manual\n    npm run test-cli\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqubitproducts%2Fbapistrano","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqubitproducts%2Fbapistrano","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqubitproducts%2Fbapistrano/lists"}