diff --git a/.ci/before_deploy.sh b/.ci/before_deploy.sh new file mode 100644 index 00000000..960ec326 --- /dev/null +++ b/.ci/before_deploy.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e + +if [[ "$GITSECRET_DIST" == "rpm" ]]; then + # To deploy `rpm`-packages this utility is needed: + sudo apt-get install -y rpm; +fi + + +if [[ ! -z "$DOCKER_DIST" ]]; then + # When making a non-container build, this step will generate + # proper manifest files: + make "deploy-${GITSECRET_DIST}"; +fi diff --git a/.ci/before_script.sh b/.ci/before_script.sh new file mode 100644 index 00000000..a3712c76 --- /dev/null +++ b/.ci/before_script.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -e + +# Docker: +if [[ ! -z "$DOCKER_DIST" ]]; then + TEMPLATE="sobolevn/git-secret-docker-$DOCKER_DIST" + DOCKERFILE_PATH=".docker/${GITSECRET_DIST}/${DOCKER_DIST}" + + # Building the local image: + docker build -t "$TEMPLATE" "$DOCKERFILE_PATH" +fi + +# Mac: +if [[ "$GITSECRET_DIST" == "brew" ]]; then + brew install "$GITSECRET_GPG_DEP" +fi + +# Local linux (standart build): +if [[ "$GITSECRET_DIST" == "none" ]] && [[ "$GITSECRET_GPG_DEP" == "gnupg2" ]]; then + # Installing custom GPG version: + sudo apt-get install -y gnupg2 +fi diff --git a/.ci/script.sh b/.ci/script.sh new file mode 100644 index 00000000..3a441376 --- /dev/null +++ b/.ci/script.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -e + +# Docker-baised builds: +if [[ ! -z "$DOCKER_DIST" ]]; then + TEMPLATE="sobolevn/git-secret-docker-$DOCKER_DIST" + # Passing the `TRAVIS_COMMIT` into the container: + COMMAND="if [ ! -z ${TRAVIS_COMMIT} ]; then git checkout ${TRAVIS_COMMIT}; fi; make test-${GITSECRET_DIST}-ci" + + # This will run the full intergration check inside the `docker` container: + # see `test-deb-ci` and `test-rpm-ci` in `Makefile` + docker run "$TEMPLATE" /bin/bash -c "$COMMAND" + docker ps -a +fi + +# Local builds: +if [[ "$GITSECRET_DIST" == "brew" ]] || [[ "$GITSECRET_DIST" == "brew" ]]; then + # Only running `make test` on standard (non-docker) build, + # since it is called inside the docker container anyway. + make test +fi + +if [[ ! -z "$(command -v shellcheck)" ]]; then + # This means, that `shellcheck` does exist, so run it: + echo 'running lint' + find src utils -type f -name '*.sh' -print0 | xargs -0 -I {} shellcheck {} + # TODO: add tests to lint + # see: https://github.com/koalaman/shellcheck/issues/709 +fi diff --git a/.docker/deb/debian/Dockerfile b/.docker/deb/debian/Dockerfile new file mode 100644 index 00000000..1ea5e015 --- /dev/null +++ b/.docker/deb/debian/Dockerfile @@ -0,0 +1,23 @@ +FROM debian:latest + +MAINTAINER Nikita Sobolev (mail@sobolevn.me) + +# Dependencies and project initialization: + +RUN apt-get update && \ + apt-get install -y man make git apt-transport-https && \ + apt-get install -y ruby ruby-dev ruby-build && \ + apt-get autoremove && apt-get autoclean + +# This will increase the container size, but speed up the build, +# since this part will change, while the dependencies won't: + +RUN mkdir /code +WORKDIR /code + +# Removing `origin` for good: + +RUN git clone -q https://github.com/sobolevn/git-secret.git && \ + cd git-secret && git remote rm origin + +WORKDIR /code/git-secret diff --git a/.docker/deb/ubuntu/Dockerfile b/.docker/deb/ubuntu/Dockerfile new file mode 100644 index 00000000..72b03ef6 --- /dev/null +++ b/.docker/deb/ubuntu/Dockerfile @@ -0,0 +1,23 @@ +FROM ubuntu:latest + +MAINTAINER Nikita Sobolev (mail@sobolevn.me) + +# Dependencies and project initialization: + +RUN apt-get update && \ + apt-get install -y man make git apt-transport-https && \ + apt-get install -y ruby ruby-dev ruby-build && \ + apt-get autoremove && apt-get autoclean && \ + mkdir /code + +# This will increase the container size, but speed up the build, +# since this part will change, while the dependencies won't: + +WORKDIR /code + +# Removing `origin` for good: + +RUN git clone -q https://github.com/sobolevn/git-secret.git && \ + cd git-secret && git remote rm origin + +WORKDIR /code/git-secret diff --git a/.docker/make/debian/Dockerfile b/.docker/make/debian/Dockerfile new file mode 100644 index 00000000..7a7a5c99 --- /dev/null +++ b/.docker/make/debian/Dockerfile @@ -0,0 +1,22 @@ +FROM debian:latest + +MAINTAINER Nikita Sobolev (mail@sobolevn.me) + +# Dependencies and project initialization: + +RUN apt-get update && \ + apt-get install -y man make git apt-transport-https && \ + apt-get autoremove && apt-get autoclean + +# This will increase the container size, but speed up the build, +# since this part will change, while the dependencies won't: + +RUN mkdir /code +WORKDIR /code + +# Removing `origin` for good: + +RUN git clone -q https://github.com/sobolevn/git-secret.git && \ + cd git-secret && git remote rm origin + +WORKDIR /code/git-secret diff --git a/.docker/rpm/fedora/Dockerfile b/.docker/rpm/fedora/Dockerfile new file mode 100644 index 00000000..2a528688 --- /dev/null +++ b/.docker/rpm/fedora/Dockerfile @@ -0,0 +1,22 @@ +FROM fedora:latest + +MAINTAINER Nikita Sobolev (mail@sobolevn.me) + +ENV HOME /root + +RUN dnf update -y && \ + dnf install -y gnupg man make gcc git tar > /dev/null && \ + dnf install -y which pciutils redhat-rpm-config rpm-build zlib-devel && \ + dnf -y group install 'Development tools' && \ + dnf install -y ruby ruby-devel rubygems && \ + dnf -y autoremove && \ + mkdir /code + +WORKDIR /code + +# Removing `origin` for good: + +RUN git clone -q https://github.com/sobolevn/git-secret.git && \ + cd git-secret && git remote rm origin + +WORKDIR /code/git-secret diff --git a/.gitignore b/.gitignore index 8135a88a..6eff042b 100644 --- a/.gitignore +++ b/.gitignore @@ -121,7 +121,16 @@ _site/ .sass-cache/ #####=== Custom ===##### +# Logic files: .gitsecret/ git-secret + +# Temporary packages: vendor/ temp/ + +# Packaging: +build/ +*.deb +*.fpm +test.txt diff --git a/.travis.yml b/.travis.yml index ebe541c7..fb99efa4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,79 @@ -language: c +matrix: + fast_finish: true + include: + - os: linux + env: GITSECRET_DIST="make"; DOCKER_DIST="debian" + services: docker + sudo: required + language: ruby + - os: linux + env: GITSECRET_DIST="deb"; DOCKER_DIST="debian"; + services: docker + sudo: required + language: ruby + - os: linux + env: GITSECRET_DIST="deb"; DOCKER_DIST="ubuntu" + services: docker + sudo: required + language: ruby + - os: linux + env: GITSECRET_DIST="rpm"; DOCKER_DIST="fedora" + services: docker + sudo: required + language: ruby + - os: linux + env: GITSECRET_DIST="none"; GITSECRET_GPG_DEP="gnupg"; SECRETS_GPG_COMMAND="gpg" + sudo: required + language: ruby + - os: linux + env: GITSECRET_DIST="none"; GITSECRET_GPG_DEP="gnupg2"; SECRETS_GPG_COMMAND="gpg2" + sudo: required + language: ruby + - os: linux + env: GITSECRET_DIST="shellcheck" + sudo: required + language: ruby + addons: + apt: + sources: + - debian-sid + packages: + - shellcheck + - os: osx + env: GITSECRET_DIST="brew"; GITSECRET_GPG_DEP="gnupg"; SECRETS_GPG_COMMAND="gpg" + sudo: false + language: generic + - os: osx + env: GITSECRET_DIST="brew"; GITSECRET_GPG_DEP="gnupg2"; SECRETS_GPG_COMMAND="gpg2" + sudo: false + language: generic -env: - - SECRETS_GPG_COMMAND=gpg - - SECRETS_GPG_COMMAND=gpg2 - -branches: - only: - - master - - develop - -install: - - test $SECRETS_GPG_COMMAND = gpg2 && sudo apt-get install gnupg2 || echo 0 - - make install-test +before_script: + - chmod +x ".ci/before_script.sh" && ".ci/before_script.sh" script: - - make test + - chmod +x ".ci/script.sh" && ".ci/script.sh" + +before_deploy: + - chmod +x ".ci/before_deploy.sh" && ".ci/before_deploy.sh" + +deploy: + - provider: bintray + on: + branch: master + condition: "$GITSECRET_DIST == deb" + file: "build/deb_descriptor.json" + user: "sobolevn" + key: "$BINTRAY_API_KEY" + passphrase: "$BINTRAY_GPG_PASS" + - provider: bintray + on: + branch: master + condition: "$GITSECRET_DIST == rpm" + file: "build/rpm_descriptor.json" + user: "sobolevn" + key: "$BINTRAY_API_KEY" + passphrase: "$BINTRAY_GPG_PASS" notifications: email: diff --git a/CHANGELOG.md b/CHANGELOG.md index ce9077ee..0202a7d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,21 @@ # Changelog +## Version 0.2.1 + +- Now everything is tested inside the `docker`-containers and `OSX` images on `travis`. +- Added autodeploy to `bintray` in `.travis.yml`. +- Added `.ci/` folder for continuous integration, refactored `utils/` folder. +- Added `CONTRIBUTING.md` and `LICENSE.md`. +- New brand logo in the `README.md`. +- Everything is `shellcheck`ed (except `tests/`). + ## Version 0.2.0 - Added `changes` command to see the difference between current version of the hidden files and the commited one - Added `-f` option to the `reveal` command to remove prompts -- Changed the way files were decrypted, now it is a separate functon +- Changed the way files were decrypted, now it is a separate function - Some bugs are fixed -- New installation instractions +- New installation instructions ## Version 0.1.2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..c94d6f74 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,93 @@ +# Contributing + +Your contributions are always welcome! + +## Process + +### Environment + +Before starting make sure you have: + +- git +- bash +- gnupg (or gnupg2) +- [shellcheck](https://github.com/koalaman/shellcheck) + +Only required if dealing with manuals, `gh-pages` or releases: + +- ruby, ruby-dev + +### Getting started + +1. Create your own or pick an opened issue from the [tracker][tracker]. Take a look at the [`help-wanted` tag][help-wanted] +2. Fork and clone your repository: `git clone https://github.com/${YOUR_NAME}/git-secret.git` +3. Make sure that everything works fine by running `make test` + +### Development Process + +1. Firstly, you will need to setup development hooks with `make install-hooks` +2. Make changes to the files that need to be changed +3. When making changes to any files inside `src/` you will need to rebuild the binary `git-secret` with `make clean && make build` command +4. Run [`shellcheck`][shellcheck] against all your changes with `find src utils -type f -name '*.sh' -print0 | xargs -0 -I {} shellcheck {}` +5. Now, add all your files to the commit with `git add --all` and commit changes with `git commit`, make sure you write a good message, which will explain your work +6. When running `git commit` the tests will run automatically, your commit will be canceled if they fail +7. Push to your repository, make a pull-request against `develop` branch. Please, make sure you have **one** commit per pull-request + +### Branches + +We have three long-live branches: `master`, `staging` and `develop` (and `gh-pages` for static site). + +It basically looks like that: + +> `your-branch` -> `develop` -> `staging` -> `master` + +- `master` branch is protected, since `antigen` and tools like it install the app from the main branch directly. So only fully tested code goes there +- `staging` - this branch is used to create a new `git` tag and a `github` release, then it gets merged into `master` +- `develop` is where the development is done and the branch you should send your pull-requests to + +### Continuous integration + +CI is done with the help of `travis`. `travis` handles multiple environments: + +- `Docker`-based jobs or so-called 'integration tests', these tests create a local release, install it with the package manager and then run unit-tests and system checks +- `OSX` jobs, which handle basic unit-tests on `OSX` +- Native `travis` jobs, which handle basic unit-tests and stylechecks + +### Release process + +The release process is defined in the `git`-hooks and `.travis.yml`. + +When creating a commit inside the `staging` branch (it is usually a documentation and changelog update with the version bump inside `src/version.sh`) it will trigger two main events. + +Firstly, new manuals will be created and added to the current commit with `make build-man` on `pre-commit` hook. + +Secondly, after the commit is successfully created it will also trigger `make build-gh-pages` target on `post-commit` hook, which will push new manuals to the [git-secret site][git-secret-site]. And the new `git` tag will be automatically created if the version is changed: + +```bash +if [[ "$NEWEST_TAG" != "v${SCRIPT_VERSION}" ]]; then + git tag -a "v${SCRIPT_VERSION}" -m "version $SCRIPT_VERSION" +fi +``` + +Then it will be merged inside `master` when ready. + +#### Travis releases + +When creating a commit inside `master` branch, `travis` on successful build will publish new `deb` and `rpm` packages to [`bintray`][bintray]. + +If you wish to override a previous release (*be careful*) you will need to add `"override": 1` into `matrixParams`, see `deb-deploy.sh` and `rpm-deploy.sh` + +#### Manual releases + +Releases to `brew` are made manually. + +#### Dockerhub releases + +[`Dockerhub`][Dockerhub] contains `Docker` images with different OS'es used for testing. It is updated via a `github` webhook on commit into `master`. + +[tracker]: https://github.com/sobolevn/git-secret/issues +[help-wanted]: https://github.com/sobolevn/git-secret/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22 +[shellcheck]: https://github.com/koalaman/shellcheck +[git-secret-site]: https://sobolevn.github.io/git-secret/ +[bintray]: https://bintray.com/sobolevn +[Dockerhub]: https://hub.docker.com/r/sobolevn/git-secret/ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..cf38dad3 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Nikita Sobolev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index f6b305c5..5ce122e8 100644 --- a/Makefile +++ b/Makefile @@ -5,13 +5,13 @@ PREFIX?="/usr" # Building: # +git-secret: src/version.sh src/_utils/* src/commands/* src/main.sh + @cat $^ > "$@"; \ + chmod +x git-secret; sync + .PHONY: all all: build -git-secret: src/_utils/* src/commands/* src/main.sh - @cat $^ > "$@" - @chmod +x git-secret - .PHONY: clean clean: @rm -f git-secret @@ -21,8 +21,13 @@ build: git-secret .PHONY: install install: - @chmod +x "./utils/install.sh" - @"./utils/install.sh" "${PREFIX}" + @chmod +x "./utils/install.sh"; sync; \ + "./utils/install.sh" "${PREFIX}" + +.PHONY: uninstall +uninstall: + @chmod +x "./utils/uninstall.sh"; sync; \ + "./utils/uninstall.sh" "${PREFIX}" # # Testing: @@ -30,15 +35,15 @@ install: .PHONY: install-test install-test: - git clone https://github.com/sstephenson/bats.git vendor/bats + @if [ ! -d "vendor/bats" ]; then \ + git clone https://github.com/sstephenson/bats.git vendor/bats; fi .PHONY: test -test: - @if [ ! -d "vendor/bats" ]; then make install-test; fi - @export SECRET_PROJECT_ROOT="${PWD}"; export PATH="${PWD}/vendor/bats/bin:${PWD}:${PATH}"; \ - make develop; \ - rm -rf temp; mkdir temp; cd temp; \ - bats "../tests"; +test: install-test clean build + @chmod +x "./utils/tests.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + export PATH="${PWD}/vendor/bats/bin:${PWD}:${PATH}"; \ + "./utils/tests.sh" # # Manuals: @@ -49,14 +54,13 @@ install-ronn: @if [ ! `gem list ronn -i` == "true" ]; then gem install ronn; fi .PHONY: build-man -build-man: - @make install-ronn - ronn --roff man/*/*.ronn +build-man: install-ronn + @ronn --roff man/*/*.ronn .PHONY: build-gh-pages build-gh-pages: - @chmod +x "./utils/gh-branch.sh" - @"./utils/gh-branch.sh" + @chmod +x "./utils/gh-branch.sh"; sync; \ + "./utils/gh-branch.sh" # # Development: @@ -64,12 +68,10 @@ build-gh-pages: .PHONY: install-hooks install-hooks: - @# pre-commit: - @ln -fs "${PWD}/utils/pre-commit.sh" "${PWD}/.git/hooks/pre-commit" - @chmod +x "${PWD}/.git/hooks/pre-commit" - @# post-commit: - @ln -fs "${PWD}/utils/post-commit.sh" "${PWD}/.git/hooks/post-commit" - @chmod +x "${PWD}/.git/hooks/post-commit" + @ln -fs "${PWD}/utils/hooks/pre-commit.sh" "${PWD}/.git/hooks/pre-commit"; \ + chmod +x "${PWD}/.git/hooks/pre-commit"; sync; \ + ln -fs "${PWD}/utils/hooks/post-commit.sh" "${PWD}/.git/hooks/post-commit"; \ + chmod +x "${PWD}/.git/hooks/post-commit"; sync .PHONY: develop develop: clean build install-hooks @@ -82,9 +84,55 @@ develop: clean build install-hooks install-fpm: @if [ ! `gem list fpm -i` == "true" ]; then gem install fpm; fi -.PHONY: build-deb -build-deb: clean build - @make install-fpm - @chmod +x "./utils/build-deb.sh" - @"./utils/build-deb.sh" +# .deb: +.PHONY: build-deb +build-deb: clean build install-fpm + @chmod +x "./utils/build-utils.sh"; sync; \ + chmod +x "./utils/deb/deb-build.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + "./utils/deb/deb-build.sh" + +.PHONY: test-deb-ci +test-deb-ci: install-test build-deb + @chmod +x "./utils/deb/deb-ci.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + export PATH="${PWD}/vendor/bats/bin:${PATH}"; \ + "./utils/deb/deb-ci.sh" + +.PHONY: deploy-deb +deploy-deb: build-deb + @chmod +x "./utils/deb/deb-deploy.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + "./utils/deb/deb-deploy.sh" + +# .rpm: + +.PHONY: build-rpm +build-rpm: clean build install-fpm + @chmod +x "./utils/build-utils.sh"; sync; \ + chmod +x "./utils/rpm/rpm-build.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + "./utils/rpm/rpm-build.sh" + +.PHONY: test-rpm-ci +test-rpm-ci: install-test build-rpm + @chmod +x "./utils/rpm/rpm-ci.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + export PATH="${PWD}/vendor/bats/bin:${PATH}"; \ + "./utils/rpm/rpm-ci.sh" + +.PHONY: deploy-rpm +deploy-rpm: build-rpm + @chmod +x "./utils/rpm/rpm-deploy.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + "./utils/rpm/rpm-deploy.sh" + +# make: + +.PHONY: test-make-ci +test-make-ci: clean install-test + @chmod +x "./utils/make/make-ci.sh"; sync; \ + export SECRET_PROJECT_ROOT="${PWD}"; \ + export PATH="${PWD}/vendor/bats/bin:${PATH}"; \ + "./utils/make/make-ci.sh" diff --git a/README.md b/README.md index a091d78b..200ceb15 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # git-secret -[![Build Status](https://secure.travis-ci.org/sobolevn/git-secret.png?branch=master)](https://travis-ci.org/sobolevn/git-secret) +[![Build Status](https://img.shields.io/travis/sobolevn/git-secret/master.svg)](https://travis-ci.org/sobolevn/git-secret) [![Homebrew](https://img.shields.io/homebrew/v/git-secret.svg)](http://braumeister.org/formula/git-secret) [![Bintray deb](https://img.shields.io/bintray/v/sobolevn/deb/git-secret.svg)](https://bintray.com/sobolevn/deb/git-secret/view) [![Dockerhub](https://img.shields.io/docker/pulls/sobolevn/git-secret.svg)](https://hub.docker.com/r/sobolevn/git-secret/) + +[![git-secret](https://raw.githubusercontent.com/sobolevn/git-secret/gh-pages/images/git-secret-big.png)](https://sobolevn.github.io/git-secret/) + +## What is `git-secret`? + +`git-secret` is a bash tool to store your private data inside a git repo. How’s that? Basically, it just encrypts, using `gpg`, the tracked files with the public keys of all the users that you trust. So everyone of them can decrypt these files using only their personal secret key. Why deal with all this private-public keys stuff? Well, to make it easier for everyone to manage access rights. There are no passwords that change. When someone is out - just delete his public key, re-encrypt the files, and he won’t be able to decrypt secrets anymore. ## Preview @@ -14,16 +20,22 @@ See the [git-secret site](https://sobolevn.github.io/git-secret/). See the [installation section](https://sobolevn.github.io/git-secret/#installation). -## Status +## Contributing +<<<<<<< HEAD This project is still under development. See [https://github.com/sobolevn/git-secret/milestones](milestones) for the reference. +======= +See [CONTRIBUTING.md](CONTRIBUTING.md). +>>>>>>> develop -## Testing +## Changelog -For testing this project uses [`bats`](https://github.com/sstephenson/bats). You can install it by running `make install-test`. -To run tests call: `make test`. It will download and install `bats` into `vendor/bats` if it's not installed yet. +See [CHANGELOG.md](CHANGELOG.md). +## License -## Changelog +MIT. See [LICENSE.md](LICENSE.md) for details. + +## Thanks -See [CHANGELOG.md](CHANGELOG.md) +Special thanks to [Elio Qoshi](https://elioqoshi.me/sq/) from [ura](http://ura.al/) for the awesome logo. diff --git a/git-secret.plugin.zsh b/git-secret.plugin.zsh index a6b73b98..61977e1f 100644 --- a/git-secret.plugin.zsh +++ b/git-secret.plugin.zsh @@ -1,3 +1,5 @@ +#!/usr/bin/env zsh + # Copyright 2016 Sobolev Nikita # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,7 +15,7 @@ # limitations under the License. # Create binary: -PLUGIN_DIR="$(dirname $0)" +PLUGIN_DIR="$(dirname "$0")" if [ ! -f "$PLUGIN_DIR/git-secret" ]; then cd "$PLUGIN_DIR" && make build && cd .. diff --git a/man/man7/git-secret.7 b/man/man7/git-secret.7 index e7e87031..2e4166d9 100644 --- a/man/man7/git-secret.7 +++ b/man/man7/git-secret.7 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "GIT\-SECRET" "7" "May 2016" "" "" +.TH "GIT\-SECRET" "7" "July 2016" "" "" . .SH "NAME" \fBgit\-secret\fR @@ -49,7 +49,7 @@ When building the automated deployment system there will be one extra step: down .SH "Installation" . .SS "Dependencies" -\fBgit secret\fR relies on two dependecies: \fBgit\fR \fIhttps://git\-scm\.com/\fR and \fBgpg\fR \fIhttps://www\.gnupg\.org/\fR\. Download and install them before using this project\. \fBgit\-secret\fR is tested to work with: +\fBgit\-secret\fR relies on two dependencies: \fBgit\fR \fIhttps://git\-scm\.com/\fR and \fBgpg\fR \fIhttps://www\.gnupg\.org/\fR\. Download and install them before using this project\. \fBgit\-secret\fR is tested to work with: . .IP "" 4 . @@ -63,13 +63,13 @@ gpg (GnuPG) 1\.4\.20 .IP "" 0 . .SS "Supported platforms" -\fBgit secret\fR works with \fBMac OS X\fR >= 10\.9, \fBUbuntu\fR >= 14\.04 and \fBDebian\fR >= 8\.3 You can add your platform to this list, if all the tests pass for you\. \fBCygwin\fR support is planned\. +\fBgit\-secret\fR works with \fBMac OS X\fR >= 10\.9, \fBUbuntu\fR >= 14\.04 and \fBDebian\fR >= 8\.3 You can add your platform to this list, if all the tests pass for you\. \fBCygwin\fR support is planned\. . .SS "Installation process" There are several ways to install \fBgit\-secret\fR: . .P -\fBBrew\fR +\fB\fBHomebrew\fR\fR . .IP "1." 4 Run \fBbrew install git\-secret\fR\. That will do\. Also, there are two options: @@ -86,29 +86,29 @@ Note, that we have migrated from \fBtap\fR to the official \fBbrew\fR repo .IP "" 0 . .P -\fBManual\fR +\fB\fB\fBdeb\fR package\fR\fR . .IP "1." 4 -Clone the repository first: \fBgit clone https://github\.com/sobolevn/git\-secret\.git git\-secret\fR +Run \fBecho "deb https://dl\.bintray\.com/sobolevn/deb git\-secret stable" | sudo tee \-a /etc/apt/sources\.list\fR . .IP "2." 4 -Run \fBPREFIX="/usr/local" make install\fR, note that you can install to any prefix in your \fBPATH\fR +Run \fBsudo apt\-get install git\-secret\fR . .IP "" 0 . .P -\fB\fBantigen\fR plugin (or any other \fBoh\-my\-zsh\fR\-styled plugin\-systems)\fR +\fB\fB\fBrpm\fR package\fR\fR . .IP "1." 4 -Add line \fBantigen bundle sobolevn/git\-secret\fR to your \fB\.zshrc\fR +Run \fBwget https://bintray\.com/sobolevn/rpm/rpm \-O bintray\-sobolevn\-rpm\.repo && sudo mv bintray\-sobolevn\-rpm\.repo /etc/yum\.repos\.d/\fR . .IP "2." 4 -Run \fBsource ~/\.zshrc\fR or reopen the terminal +Run \fBsudo yum install git\-secret\fR . .IP "" 0 . .P -\fBThe hard way\fR +\fB\fBManual\fR\fR . .IP "1." 4 Clone the repository first: \fBgit clone https://github\.com/sobolevn/git\-secret\.git git\-secret\fR @@ -117,21 +117,18 @@ Clone the repository first: \fBgit clone https://github\.com/sobolevn/git\-secre Run \fBcd git\-secret && make build\fR . .IP "3." 4 -Move \fBgit\-secret\fR file and \fBman/\fR folder somewhere inside your \fB$PATH\fR, or extend your \fB$PATH\fR to contain \fBgit\-secret\fR file and \fBman/\fR folder +Run \fBPREFIX="/usr/local" make install\fR, note that you can install to any prefix in your \fBPATH\fR . .IP "" 0 . .P -\fBLocal \fB\.deb\fR package\fR +\fB\fB\fBantigen\fR plugin (or any other \fBoh\-my\-zsh\fR\-styled plugin\-systems)\fR\fR . .IP "1." 4 -Download the latest realease here \fIhttps://github\.com/sobolevn/git\-secret/releases\fR +Add line \fBantigen bundle sobolevn/git\-secret\fR to your \fB~/\.zshrc\fR . .IP "2." 4 -Unpack, and run \fBmake build\-deb\fR, it is possible to set the output folder with \fB$SCRIPT_BUILD_DIR\fR variable\. -. -.IP "3." 4 -Install the local \fB\.deb\fR package with \fBdpkp \-i git\-secret\-package\-name\.deb\fR, note that this command may require \fBsudo\fR and the package name will be different +Run \fBsource ~/\.zshrc\fR or reopen the terminal . .IP "" 0 . @@ -142,13 +139,13 @@ These steps cover the basic process of using \fBgit\-secret\fR: Before starting, make sure you have created \fBgpg\fR RSA key\-pair: public and secret key identified by your email address\. . .IP "2." 4 -Initialize \fBgit\-secret\fR repository by running \fBgit secret init\fR command\. \fB\.gitsecret/\fR folder will be created\. +Initialize \fBgit\-secret\fR repository by running \fBgit secret init\fR command\. \fB\.gitsecret/\fR folder will be created, \fBnote\fR that \fB\.gitsecret/\fR folder should \fBnot\fR be ignored \fIhttps://github\.com/sobolevn/git\-secret/issues/39\fR\. . .IP "3." 4 -Add first user to the system by running \fBgit secret tell your@gpg\.email\-id\fR\. +Add first user to the system by running \fBgit secret tell your@gpg\.email\fR\. . .IP "4." 4 -Now it\'s time to add files you wish to encrypt inside the \fBgit\-secret\fR repository\. It can be done by running \fBgit secret add \fR command\. Make sure these files are ignored, otherwise \fBgit secret\fR won\'t allow you to add them, as these files will be stored unencrypted\. +Now it\'s time to add files you wish to encrypt inside the \fBgit\-secret\fR repository\. It can be done by running \fBgit secret add \fR command\. Make sure these files are ignored, otherwise \fBgit\-secret\fR won\'t allow you to add them, as these files will be stored unencrypted\. . .IP "5." 4 When done, run \fBgit secret hide\fR all files, which you have added by \fBgit secret add\fR command will be encrypted with added public\-keys by the \fBgit secret tell\fR command\. Now it is safe to commit your changes\. \fBBut\fR\. It\'s recommended to add \fBgit secret hide\fR command to your \fBpre\-commit\fR hook, so you won\'t miss any changes\. diff --git a/man/man7/git-secret.7.ronn b/man/man7/git-secret.7.ronn index 1f685c4f..af3553e6 100644 --- a/man/man7/git-secret.7.ronn +++ b/man/man7/git-secret.7.ronn @@ -25,14 +25,14 @@ There's a known problem in server configuration and deploying, when you have to ### Dependencies -`git secret` relies on two dependecies: [`git`][1] and [`gpg`][2]. Download and install them before using this project. `git-secret` is tested to work with: +`git-secret` relies on two dependencies: [`git`][1] and [`gpg`][2]. Download and install them before using this project. `git-secret` is tested to work with: git version 2.7.0 gpg (GnuPG) 1.4.20 ### Supported platforms -`git secret` works with `Mac OS X` >= 10.9, `Ubuntu` >= 14.04 and `Debian` >= 8.3 +`git-secret` works with `Mac OS X` >= 10.9, `Ubuntu` >= 14.04 and `Debian` >= 8.3 You can add your platform to this list, if all the tests pass for you. `Cygwin` support is planned. @@ -40,42 +40,42 @@ You can add your platform to this list, if all the tests pass for you. There are several ways to install `git-secret`: -**Brew** +**** Homebrew **** 1. Run `brew install git-secret`. That will do. Also, there are two options: * `--without-gpg` to build without `gpg` support * `--HEAD` to install `HEAD` version 2. Note, that we have migrated from `tap` to the official `brew` repo -**Manual** +**** `deb` package **** -1. Clone the repository first: `git clone https://github.com/sobolevn/git-secret.git git-secret` -2. Run `PREFIX="/usr/local" make install`, note that you can install to any prefix in your `PATH` +1. Run `echo "deb https://dl.bintray.com/sobolevn/deb git-secret stable" | sudo tee -a /etc/apt/sources.list` +2. Run `sudo apt-get install git-secret` -**`antigen` plugin (or any other `oh-my-zsh`-styled plugin-systems)** +**** `rpm` package **** -1. Add line `antigen bundle sobolevn/git-secret` to your `.zshrc` -2. Run `source ~/.zshrc` or reopen the terminal +1. Run `wget https://bintray.com/sobolevn/rpm/rpm -O bintray-sobolevn-rpm.repo && sudo mv bintray-sobolevn-rpm.repo /etc/yum.repos.d/` +2. Run `sudo yum install git-secret` -**The hard way** +**** Manual **** 1. Clone the repository first: `git clone https://github.com/sobolevn/git-secret.git git-secret` 2. Run `cd git-secret && make build` -3. Move `git-secret` file and `man/` folder somewhere inside your `$PATH`, or extend your `$PATH` to contain `git-secret` file and `man/` folder +3. Run `PREFIX="/usr/local" make install`, note that you can install to any prefix in your `PATH` -**Local `.deb` package** +**** `antigen` plugin (or any other `oh-my-zsh`-styled plugin-systems) **** + +1. Add line `antigen bundle sobolevn/git-secret` to your `~/.zshrc` +2. Run `source ~/.zshrc` or reopen the terminal -1. Download the latest realease [here](https://github.com/sobolevn/git-secret/releases) -2. Unpack, and run `make build-deb`, it is possible to set the output folder with `$SCRIPT_BUILD_DIR` variable. -3. Install the local `.deb` package with `dpkp -i git-secret-package-name.deb`, note that this command may require `sudo` and the package name will be different ## Usage These steps cover the basic process of using `git-secret`: 0. Before starting, make sure you have created `gpg` RSA key-pair: public and secret key identified by your email address. -1. Initialize `git-secret` repository by running `git secret init` command. `.gitsecret/` folder will be created. -2. Add first user to the system by running `git secret tell your@gpg.email-id`. -3. Now it's time to add files you wish to encrypt inside the `git-secret` repository. It can be done by running `git secret add ` command. Make sure these files are ignored, otherwise `git secret` won't allow you to add them, as these files will be stored unencrypted. +1. Initialize `git-secret` repository by running `git secret init` command. `.gitsecret/` folder will be created, **note** that `.gitsecret/` folder [should **not** be ignored](https://github.com/sobolevn/git-secret/issues/39). +2. Add first user to the system by running `git secret tell your@gpg.email`. +3. Now it's time to add files you wish to encrypt inside the `git-secret` repository. It can be done by running `git secret add ` command. Make sure these files are ignored, otherwise `git-secret` won't allow you to add them, as these files will be stored unencrypted. 4. When done, run `git secret hide` all files, which you have added by `git secret add` command will be encrypted with added public-keys by the `git secret tell` command. Now it is safe to commit your changes. **But**. It's recommended to add `git secret hide` command to your `pre-commit` hook, so you won't miss any changes. 5. Now decrypt files with `git secret reveal` command. It will ask you for your password. And you're done! diff --git a/src/_utils/_git_secret_tools.sh b/src/_utils/_git_secret_tools.sh index 99c8c7e9..b574bbfc 100644 --- a/src/_utils/_git_secret_tools.sh +++ b/src/_utils/_git_secret_tools.sh @@ -1,9 +1,7 @@ #!/usr/bin/env bash -GITSECRET_VERSION="0.2.0" - # Global variables: -WORKING_DIRECTORY="$PWD" +WORKING_DIRECTORY="$PWD" # shellcheck disable=2034 # Folders: SECRETS_DIR=".gitsecret" @@ -11,15 +9,15 @@ SECRETS_DIR_KEYS="$SECRETS_DIR/keys" SECRETS_DIR_PATHS="$SECRETS_DIR/paths" # Files: -SECRETS_DIR_KEYS_MAPPING="$SECRETS_DIR_KEYS/mapping.cfg" -SECRETS_DIR_KEYS_TRUSTDB="$SECRETS_DIR_KEYS/trustdb.gpg" +SECRETS_DIR_KEYS_MAPPING="$SECRETS_DIR_KEYS/mapping.cfg" # shellcheck disable=2034 +SECRETS_DIR_KEYS_TRUSTDB="$SECRETS_DIR_KEYS/trustdb.gpg" # shellcheck disable=2034 -SECRETS_DIR_PATHS_MAPPING="$SECRETS_DIR_PATHS/mapping.cfg" +SECRETS_DIR_PATHS_MAPPING="$SECRETS_DIR_PATHS/mapping.cfg" # shellcheck disable=2034 -: ${SECRETS_EXTENSION:=".secret"} +: "${SECRETS_EXTENSION:=".secret"}" # Commands: -: ${SECRETS_GPG_COMMAND:="gpg"} +: "${SECRETS_GPG_COMMAND:="gpg"}" GPGLOCAL="$SECRETS_GPG_COMMAND --homedir=$SECRETS_DIR_KEYS --no-permission-warning" @@ -40,11 +38,11 @@ function _os_based { case "$(uname -s)" in Darwin) - $1_osx ${@:2} + "$1_osx" "${@:2}" ;; Linux) - $1_linux ${@:2} + "$1_linux" "${@:2}" ;; # TODO: add MS Windows support. @@ -65,10 +63,11 @@ function _set_config { # First parameter is the KEY, second is VALUE, third is filename. # The exit status is 0 (true) if the name was found, 1 (false) if not: - local contains=$(grep -Fq "$1" $3; echo $?) + local contains + contains=$(grep -Fq "$1" "$3"; echo "$?") if [[ "$contains" -eq 0 ]]; then - _os_based __replace_in_file $@ + _os_based __replace_in_file "$@" elif [[ "$contains" -eq 1 ]]; then echo "$1 = $2" >> "$3" fi @@ -78,14 +77,16 @@ function _set_config { function _file_has_line { # First parameter is the KEY, second is the filename. - local contains=$(grep -qw "$1" "$2"; echo $?) + local contains + contains=$(grep -qw "$1" "$2"; echo $?) # 0 on contains, 1 for error. echo "$contains"; } function _delete_line { - local escaped_path=$(echo "$1" | sed -e 's/[\/&]/\\&/g') + local escaped_path + escaped_path=$(echo "$1" | sed -e 's/[\/&]/\\&/g') sed -i.bak "/$escaped_path/d" "$2" } @@ -95,7 +96,7 @@ function _temporary_file { # which will be removed on system exit. filename=$(_os_based __temp_file) # is not `local` on purpose. - trap "echo 'cleaning up...'; rm -f $filename;" EXIT + trap 'echo "cleaning up..."; rm -f "$filename";' EXIT } @@ -103,15 +104,15 @@ function _unique_filename { # First parameter is base-path, second is filename, # third is optional extension. local n=0 result=$2 - while [[ 1 ]]; do + while true; do if [[ ! -f "$1/$result" ]]; then break fi - n=$(( $n + 1 )) - result="$2-$n" + n=$(( n + 1 )) + result="${2}-${n}" done - echo $result + echo "$result" } @@ -164,7 +165,8 @@ function _user_required { _abort "$error_message" fi - local keys_exist=$($GPGLOCAL -n --list-keys --with-colon) + local keys_exist + keys_exist=$($GPGLOCAL -n --list-keys --with-colon) if [[ -z "$keys_exist" ]]; then _abort "$error_message" fi @@ -177,18 +179,22 @@ function _get_raw_filename { function _get_encrypted_filename { - echo "$(dirname "$1")/$(basename "$1" "$SECRETS_EXTENSION")$SECRETS_EXTENSION" | sed -e 's#^\./##' + local filename + filename="$(dirname "$1")/$(basename "$1" "$SECRETS_EXTENSION")" + echo "${filename}${SECRETS_EXTENSION}" | sed -e 's#^\./##' } function _get_users_in_keyring { - local result=$($GPGLOCAL --list-public-keys --with-colon | sed -n 's/.*<\(.*\)>.*/\1/p') + local result + result=$($GPGLOCAL --list-public-keys --with-colon | sed -n 's/.*<\(.*\)>.*/\1/p') echo "$result" } function _get_recepients { - local result=$($GPGLOCAL --list-public-keys --with-colon | sed -n 's/.*<\(.*\)>.*/-r\1/p') + local result + result=$($GPGLOCAL --list-public-keys --with-colon | sed -n 's/.*<\(.*\)>.*/-r\1/p') echo "$result" } @@ -203,12 +209,13 @@ function _decrypt { local homedir=${4:-""} local passphrase=${5:-""} - local encrypted_filename=$(_get_encrypted_filename "$filename") + local encrypted_filename + encrypted_filename=$(_get_encrypted_filename "$filename") - local base="$SECRETS_GPG_COMMAND --use-agent -q --decrypt" + local base="$SECRETS_GPG_COMMAND --use-agent -q --decrypt --no-permission-warning" if [[ "$write_to_file" -eq 1 ]]; then - base="$base -o "${filename}"" + base="$base -o $filename" fi if [[ "$force" -eq 1 ]]; then @@ -220,7 +227,8 @@ function _decrypt { fi if [[ ! -z "$passphrase" ]]; then - echo "$passphrase" | $base --batch --yes --no-tty --passphrase-fd 0 "$encrypted_filename" + echo "$passphrase" | $base --batch --yes --no-tty --passphrase-fd 0 \ + "$encrypted_filename" else $base "$encrypted_filename" fi diff --git a/src/_utils/_git_secret_tools_linux.sh b/src/_utils/_git_secret_tools_linux.sh index 514eb069..072787bd 100644 --- a/src/_utils/_git_secret_tools_linux.sh +++ b/src/_utils/_git_secret_tools_linux.sh @@ -7,6 +7,7 @@ function __replace_in_file_linux { function __temp_file_linux { - local filename=$(mktemp) + local filename + filename=$(mktemp) echo "$filename" } diff --git a/src/_utils/_git_secret_tools_osx.sh b/src/_utils/_git_secret_tools_osx.sh index 7dcc23a2..582bb0a3 100644 --- a/src/_utils/_git_secret_tools_osx.sh +++ b/src/_utils/_git_secret_tools_osx.sh @@ -8,6 +8,7 @@ function __replace_in_file_osx { function __temp_file_osx { : "${TMPDIR:=/tmp}" - local filename=$(mktemp -t _gitsecrets_XXX ) + local filename + filename=$(mktemp -t _gitsecrets_XXX ) echo "$filename"; } diff --git a/src/commands/git_secret_add.sh b/src/commands/git_secret_add.sh index 69714ba1..29da19d1 100644 --- a/src/commands/git_secret_add.sh +++ b/src/commands/git_secret_add.sh @@ -18,29 +18,33 @@ function add { _user_required local not_ignored=() + local items=( "$@" ) - for item in $@; do + for item in "${items[@]}"; do # Checking if all files in options are ignored: if [[ ! -f "$item" ]]; then _abort "$item is not a file." fi - local ignored=$(_check_ignore "$item") + local ignored + ignored=$(_check_ignore "$item") if [[ ! "$ignored" -eq 0 ]]; then - # collect unignored files. + # Collect unignored files. not_ignored+=("$item") fi done if [[ ! "${#not_ignored[@]}" -eq 0 ]]; then - # and show them all at once. - local message="these files are not ignored: ${not_ignored[@]} ;" + # And show them all at once. + local message + message="these files are not ignored: $* ;" + if [[ "$auto_add" -eq 0 ]]; then - # this file is not ignored. user don't want it to be added automatically. - # raise the exception, since all files, which will be hidden, must be ignored. + # This file is not ignored. user don't want it to be added automatically. + # Raise the exception, since all files, which will be hidden, must be ignored. _abort "$message" else - # in this case these files should be added to the `.gitignore` automatically: + # In this case these files should be added to the `.gitignore` automatically: # see https://github.com/sobolevn/git-secret/issues/18 for more. echo "$message" echo "auto adding them to .gitignore" @@ -50,9 +54,10 @@ function add { fi fi - for item in $@; do - # adding files into system, skipping duplicates. - local already_in=$(_file_has_line "$item" "$SECRETS_DIR_PATHS_MAPPING") + for item in "${items[@]}"; do + # Adding files into system, skipping duplicates. + local already_in + already_in=$(_file_has_line "$item" "$SECRETS_DIR_PATHS_MAPPING") if [[ "$already_in" -eq 1 ]]; then echo "$item" >> "$SECRETS_DIR_PATHS_MAPPING" fi diff --git a/src/commands/git_secret_changes.sh b/src/commands/git_secret_changes.sh index 27b0405a..b669cda9 100644 --- a/src/commands/git_secret_changes.sh +++ b/src/commands/git_secret_changes.sh @@ -1,11 +1,13 @@ #!/usr/bin/env bash function changes { + local passphrase="" + OPTIND=1 - while getopts "hd:p:" opt; do + while getopts 'hd:p:' opt; do case "$opt" in - h) _show_manual_for "changes";; + h) _show_manual_for 'changes';; p) passphrase=$OPTARG;; @@ -14,7 +16,7 @@ function changes { done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift local filenames="$1" if [[ -z "$filenames" ]]; then @@ -22,18 +24,21 @@ function changes { filenames=$(git secret list) fi - local previous_commit=$(git rev-parse HEAD) - - for filename in "$filenames"; do - # Meta information: - local encrypted_filename=$(_get_encrypted_filename "$filename") - local last_encrypted=$(git show "${previous_commit}:${encrypted_filename}") + IFS=' + ' + for filename in $filenames; do + local decrypted + local content + local diff_result # Now we have all the data required: - local decrypted=$(_decrypt "$filename" "0" "0" "$homedir" "$passphrase") - local content=$(cat "$filename") + decrypted=$(_decrypt "$filename" "0" "0" "$homedir" "$passphrase") + content=$(cat "$filename") - local diff_result=$(diff <(echo "$decrypted") <(echo "$content")) + # Let's diff the result: + diff_result=$(diff <(echo "$decrypted") <(echo "$content")) || true + # There was a bug in the previous version, since `diff` returns + # exit code `1` when the files are different. echo "changes in ${filename}: ${diff_result}" done } diff --git a/src/commands/git_secret_clean.sh b/src/commands/git_secret_clean.sh index f0061685..7068a05a 100644 --- a/src/commands/git_secret_clean.sh +++ b/src/commands/git_secret_clean.sh @@ -1,24 +1,30 @@ #!/usr/bin/env bash + function clean { + local verbose='' + OPTIND=1 - local verbose="" - while getopts "vh" opt; do + while getopts 'vh' opt; do case "$opt" in v) verbose="v";; - h) _show_manual_for "clean";; + h) _show_manual_for 'clean';; esac done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift - [[ ! -z "$verbose" ]] && echo && echo "cleaing:" || : # bug with custom bash on OSX + if [[ ! -z "$verbose" ]]; then + echo && echo 'cleaing:' + fi - find . -name *$SECRETS_EXTENSION -type f | xargs rm -f$verbose + find . -name "*$SECRETS_EXTENSION" -type f -print0 | xargs rm -f$verbose - [[ ! -z "$verbose" ]] && echo || : # bug with custom bash on OSX + if [[ ! -z "$verbose" ]]; then + echo + fi } diff --git a/src/commands/git_secret_hide.sh b/src/commands/git_secret_hide.sh index a602e085..ec781bc7 100644 --- a/src/commands/git_secret_hide.sh +++ b/src/commands/git_secret_hide.sh @@ -4,20 +4,20 @@ function _optional_clean { OPTIND=1 local clean=0 - local opt_string="" + local opt_string='' - while getopts "cvh" opt; do + while getopts 'cvh' opt; do case "$opt" in c) clean=1;; - h) _show_manual_for "hide";; + h) _show_manual_for 'hide';; - v) opt_string="-v";; + v) opt_string='-v';; esac done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift _user_required @@ -28,14 +28,19 @@ function _optional_clean { function hide { - _optional_clean $@ + _optional_clean "$@" local counter=0 - while read line; do - local encrypted_filename=$(_get_encrypted_filename $line) + while read -r line; do + local encrypted_filename + encrypted_filename=$(_get_encrypted_filename "$line") - local recipients=$(_get_recepients) - $GPGLOCAL --use-agent --yes --trust-model=always --encrypt $recipients -o "$encrypted_filename" "$line" + local recipients + recipients=$(_get_recepients) + + # shellcheck disable=2086 + $GPGLOCAL --use-agent --yes --trust-model=always --encrypt \ + $recipients -o "$encrypted_filename" "$line" counter=$((counter+1)) done < "$SECRETS_DIR_PATHS_MAPPING" diff --git a/src/commands/git_secret_init.sh b/src/commands/git_secret_init.sh index d49f4583..850f6893 100644 --- a/src/commands/git_secret_init.sh +++ b/src/commands/git_secret_init.sh @@ -4,20 +4,21 @@ function init { OPTIND=1 - while getopts "h" opt; do + while getopts 'h' opt; do case "$opt" in - h) _show_manual_for "init";; + h) _show_manual_for 'init';; esac done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift if [[ -d "$SECRETS_DIR" ]]; then - _abort "already inited." + _abort 'already inited.' fi - local ignores=$(_check_ignore "$SECRETS_DIR"/) + local ignores + ignores=$(_check_ignore "$SECRETS_DIR"/) if [[ ! $ignores -eq 1 ]]; then _abort "'${SECRETS_DIR}/' is ignored." diff --git a/src/commands/git_secret_killperson.sh b/src/commands/git_secret_killperson.sh index c3b3909b..371a2bb2 100644 --- a/src/commands/git_secret_killperson.sh +++ b/src/commands/git_secret_killperson.sh @@ -4,9 +4,9 @@ function killperson { OPTIND=1 - while getopts "h" opt; do + while getopts 'h' opt; do case "$opt" in - h) _show_manual_for "killperson";; + h) _show_manual_for 'killperson';; esac done diff --git a/src/commands/git_secret_list.sh b/src/commands/git_secret_list.sh index 7e7ff0ab..7a8862dc 100644 --- a/src/commands/git_secret_list.sh +++ b/src/commands/git_secret_list.sh @@ -4,14 +4,14 @@ function list { OPTIND=1 - while getopts "h?" opt; do + while getopts 'h' opt; do case "$opt" in - h) _show_manual_for "list";; + h) _show_manual_for 'list';; esac done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift _user_required @@ -19,7 +19,7 @@ function list { _abort "$SECRETS_DIR_PATHS_MAPPING is missing." fi - while read line; do + while read -r line; do echo "$line" done < "$SECRETS_DIR_PATHS_MAPPING" } diff --git a/src/commands/git_secret_remove.sh b/src/commands/git_secret_remove.sh index 455e6f1c..2a7259c7 100644 --- a/src/commands/git_secret_remove.sh +++ b/src/commands/git_secret_remove.sh @@ -2,40 +2,41 @@ function remove { - OPTIND=1 local clean=0 - while getopts "ch" opt; do + OPTIND=1 + + while getopts 'ch' opt; do case "$opt" in c) clean=1;; - h) _show_manual_for "remove";; + h) _show_manual_for 'remove';; esac done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift - # validate if user exist: + # Validate if user exists: _user_required - for item in $@; do + for item in "$@"; do if [[ ! -f "$item" ]]; then _abort "$item is not a file." fi _delete_line "$item" "$SECRETS_DIR_PATHS_MAPPING" - rm -f "${SECRETS_DIR_PATHS_MAPPING}.bak" + rm -f "${SECRETS_DIR_PATHS_MAPPING}.bak" # not all systems create '.bak' if [[ "$clean" == 1 ]]; then - local encrypted_filename=$(_get_encrypted_filename "$item") + local encrypted_filename + encrypted_filename=$(_get_encrypted_filename "$item") + rm -f "$encrypted_filename" fi done - local all=${@} - - echo "removed from index." - echo "ensure that files: [$all] are now not ignored." + echo 'removed from index.' + echo "ensure that files: [$*] are now not ignored." } diff --git a/src/commands/git_secret_reveal.sh b/src/commands/git_secret_reveal.sh index 2b1d2452..7f6a389c 100644 --- a/src/commands/git_secret_reveal.sh +++ b/src/commands/git_secret_reveal.sh @@ -2,15 +2,15 @@ function reveal { + local homedir='' + local passphrase='' + local force=0 OPTIND=1 - local homedir="" - local passphrase="" - local force=0 - while getopts "hfd:p:" opt; do + while getopts 'hfd:p:' opt; do case "$opt" in - h) _show_manual_for "reveal";; + h) _show_manual_for 'reveal';; f) force=1;; @@ -21,13 +21,13 @@ function reveal { done shift $((OPTIND-1)) - [ "$1" = "--" ] && shift + [ "$1" = '--' ] && shift _user_required local counter=0 - while read line; do - # the parameters are: filename, force, homedir, passphrase + while read -r line; do + # The parameters are: filename, write-to-file, force, homedir, passphrase _decrypt "$line" "1" "$force" "$homedir" "$passphrase" counter=$((counter+1)) diff --git a/src/commands/git_secret_tell.sh b/src/commands/git_secret_tell.sh index 0bbfc151..efdcc316 100644 --- a/src/commands/git_secret_tell.sh +++ b/src/commands/git_secret_tell.sh @@ -2,15 +2,13 @@ function tell { - _secrets_dir_exists + local email + local homedir # A POSIX variable # Reset in case getopts has been used previously in the shell. OPTIND=1 - local email - local homedir - while getopts "h?md:" opt; do case "$opt" in h) _show_manual_for "tell";; @@ -26,6 +24,9 @@ function tell { shift $((OPTIND-1)) [ "$1" = "--" ] && shift + # Moved to enable viewing a manual without validation: + _secrets_dir_exists + # Custom argument-parsing: if [[ -z $email ]]; then # Email was not set via `-m` and is in $1: @@ -33,18 +34,20 @@ function tell { fi # This file will be removed automatically: - _temporary_file + _temporary_file # note, that `_temporary_file` will export `filename` var. + # shellcheck disable=2154 local keyfile="$filename" if [[ -z "$homedir" ]]; then $SECRETS_GPG_COMMAND --export -a "$email" > "$keyfile" else # It means that homedir is set as an extra argument via `-d`: - $SECRETS_GPG_COMMAND --no-permission-warning --homedir="$homedir" --export -a "$email" > "$keyfile" + $SECRETS_GPG_COMMAND --no-permission-warning --homedir="$homedir" \ + --export -a "$email" > "$keyfile" fi if [[ ! -s "$keyfile" ]]; then - _abort 'gpg key is empty. check your key name: `gpg --list-keys`.' + _abort 'gpg key is empty. check your key name: "gpg --list-keys".' fi # Importing public key to the local keychain: diff --git a/src/commands/git_secret_whoknows.sh b/src/commands/git_secret_whoknows.sh index 66a8267b..9b35c854 100644 --- a/src/commands/git_secret_whoknows.sh +++ b/src/commands/git_secret_whoknows.sh @@ -13,8 +13,12 @@ function whoknows { shift $((OPTIND-1)) [ "$1" = "--" ] && shift + # Validating, that we have a user: _user_required - local keys=$(_get_users_in_keyring) + local keys + + # Just to the point: + keys=$(_get_users_in_keyring) echo "$keys" } diff --git a/src/main.sh b/src/main.sh index 7c7964eb..a4884751 100755 --- a/src/main.sh +++ b/src/main.sh @@ -9,16 +9,17 @@ function _check_setup { fi # Checking if the '.gitsecret' is not ignored: - local ignored=$(_check_ignore ".gitsecret/") + local ignored + ignored=$(_check_ignore ".gitsecret/") if [[ ! $ignored -eq 1 ]]; then - _abort ".gitsecret folder is ignored." + _abort '.gitsecret folder is ignored.' fi # Checking gpg setup: local secring="$SECRETS_DIR_KEYS/secring.gpg" if [[ -f $secring ]] && [[ -s $secring ]]; then # secring.gpg is not empty, someone has imported a private key. - _abort "it seems that someone has imported a secret key." + _abort 'it seems that someone has imported a secret key.' fi } @@ -38,17 +39,17 @@ function _show_version { function _init_script { if [[ $# == 0 ]]; then - _incorrect_usage "no input parameters provided." 126 + _incorrect_usage 'no input parameters provided.' 126 fi # Parse plugin-level options: local dry_run=0 - while [[ $# > 0 ]]; do + while [[ $# -gt 0 ]]; do local opt="$1" case "$opt" in - # options for quick-exit strategy: + # Options for quick-exit strategy: --dry-run) dry_run=1 shift;; @@ -60,14 +61,11 @@ function _init_script { done if [[ "$dry_run" == 0 ]]; then - # checking for proper set-up: + # Checking for proper set-up: _check_setup - # load dependencies: - # for f in ${0%/*}/src/*/*; do [[ -f "$f" ]] && . "$f"; done - - # routing the input command: - if [[ $(_function_exists $1) == 0 ]] && [[ ! $1 == _* ]]; then + # Routing the input command: + if [[ $(_function_exists "$1") == 0 ]] && [[ ! $1 == _* ]]; then $1 "${@:2}" else # TODO: elif [[ $(_plugin_exists $1) == 0 ]]; then _incorrect_usage "command $1 not found." 126 @@ -76,4 +74,4 @@ function _init_script { } -_init_script $@ +_init_script "$@" diff --git a/src/version.sh b/src/version.sh new file mode 100644 index 00000000..eb715ac9 --- /dev/null +++ b/src/version.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +GITSECRET_VERSION='0.2.1' # shellcheck disable=2034 diff --git a/tests/_test_base.bash b/tests/_test_base.bash index f62b85c5..0ea845a6 100644 --- a/tests/_test_base.bash +++ b/tests/_test_base.bash @@ -3,6 +3,7 @@ # This file is following a name convention defined in: # https://github.com/sstephenson/bats +source "$SECRET_PROJECT_ROOT/src/version.sh" source "$SECRET_PROJECT_ROOT/src/_utils/_git_secret_tools.sh" # Constants: @@ -36,7 +37,7 @@ function test_user_email { # GPG: -function _get_gpg_fingerprint_by_email { +function get_gpg_fingerprint_by_email { local email="$1" local fingerprint=$($GPGTEST --list-public-keys --with-fingerprint --with-colons | \ sed -e '/<'$email'>::scESC:/,/[A-Z0-9]\{40\}:/!d' | \ @@ -108,17 +109,20 @@ function git_set_config_email { } -function git_restore_default_email { - git config --local user.email "$1" -} - - function git_commit { git_set_config_email "$1" - git config --local user.name "Your Name" + + local user_name=$(git config user.name) + local commit_gpgsign=$(git config commit.gpgsign) + + git config --local user.name "$TEST_DEFAULT_USER" + git config --local commit.gpgsign false git add --all git commit -m "$2" + + git config --local user.name "$user_name" + git config --local commit.gpgsign "$commit_gpgsign" } diff --git a/tests/test_changes.bats b/tests/test_changes.bats index 1782d58e..b151b22e 100644 --- a/tests/test_changes.bats +++ b/tests/test_changes.bats @@ -3,6 +3,7 @@ load _test_base FILE_TO_HIDE="file_to_hide" +SECOND_FILE_TO_HIDE="second_file_to_hide" FILE_CONTENTS="hidden content юникод" FINGERPRINT="" @@ -15,6 +16,7 @@ function setup { set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" + set_state_secret_add "$SECOND_FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_hide } @@ -26,16 +28,16 @@ function teardown { } -@test "run 'changes' without previous commit" { +@test "run 'changes' with one file changed" { local password=$(test_user_password "$TEST_DEFAULT_USER") local new_content="new content" echo "$new_content" >> "$FILE_TO_HIDE" - run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" + run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -eq 0 ] # Testing that output has both filename and changes: - [[ "$output" == *"$FILE_TO_HIDE"* ]] + [[ "$output" == *"changes in $FILE_TO_HIDE"* ]] [[ "$output" == *"$new_content"* ]] } @@ -47,14 +49,20 @@ function teardown { } -@test "run 'changes' with commit" { - git_commit "$(test_user_email $TEST_DEFAULT_USER)" 'initial' +@test "run 'changes' with multiple files changed" { local password=$(test_user_password "$TEST_DEFAULT_USER") - - echo "new content" >> "$FILE_TO_HIDE" + local new_content="new content" + local second_new_content="something different" + echo "$new_content" >> "$FILE_TO_HIDE" + echo "$second_new_content" >> "$SECOND_FILE_TO_HIDE" run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] - [[ "$output" == *"$FILE_TO_HIDE"* ]] + + # Testing that output has both filename and changes: + [[ "$output" == *"changes in $FILE_TO_HIDE"* ]] [[ "$output" == *"$new_content"* ]] + + [[ "$output" == *"changes in $SECOND_FILE_TO_HIDE"* ]] + [[ "$output" == *"$second_file_to_hide"* ]] } diff --git a/tests/test_clean.bats b/tests/test_clean.bats new file mode 100644 index 00000000..882527c1 --- /dev/null +++ b/tests/test_clean.bats @@ -0,0 +1,3 @@ +#!/usr/bin/env bats + +# TODO: create tests for this command. diff --git a/tests/test_killperson.bats b/tests/test_killperson.bats index 81647d32..b749623b 100644 --- a/tests/test_killperson.bats +++ b/tests/test_killperson.bats @@ -8,10 +8,6 @@ function setup { set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" - - # init_git_repository - # git_secret_init - # git_secret_tell_test } diff --git a/tests/test_remove.bats b/tests/test_remove.bats index b54cd823..0135e259 100644 --- a/tests/test_remove.bats +++ b/tests/test_remove.bats @@ -26,6 +26,9 @@ function teardown { uninstall_fixture_full_key "$TEST_DEFAULT_USER" unset_current_state rm -f "$FIRST_FILE" "$SECOND_FILE" + + # This needs to be cleaned + rm -rf "$FOLDER" } diff --git a/utils/build-deb.sh b/utils/build-deb.sh deleted file mode 100755 index e20af392..00000000 --- a/utils/build-deb.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# Initializing and settings: -READ_PEM=0644 -EXEC_PEM=0755 - -SCRIPT_NAME="git-secret" -SCRIPT_DESCRIPTION="A bash-tool to store your private data inside a git repository." -SCRIPT_VERSION=$(bash ${PWD}/git-secret --version) -: ${SCRIPT_EPOCH:=0} -: ${SCRIPT_ITERATION:=1} - -if [[ -z "$SCRIPT_BUILD_DIR" ]]; then - SCRIPT_BUILD_DIR="${HOME}/debbuild-${SCRIPT_NAME}" -fi - -SCRIPT_DEST_DIR="${SCRIPT_BUILD_DIR}/installroot" - -# Preparing the files -rm -rf "$SCRIPT_BUILD_DIR" -mkdir -p "$SCRIPT_DEST_DIR" - -# Coping the files inside the build folder: -install -D -T -b -m "$EXEC_PEM" -T "git-secret" "${SCRIPT_DEST_DIR}/usr/bin/git-secret" -install -m "$READ_PEM" -d "${SCRIPT_DEST_DIR}/usr/share/man/man1" -install -m "$READ_PEM" -d "${SCRIPT_DEST_DIR}/usr/share/man/man7" -for file in man/man1/* ; do - if [[ "$file" == *.ronn ]]; then - continue - fi - - install -D -T -b -m "$READ_PEM" -T "$file" "${SCRIPT_DEST_DIR}/usr/share/${file}" -done -install -D -T -b -m "$READ_PEM" -T "man/man7/git-secret.7" \ - "${SCRIPT_DEST_DIR}/usr/share/man/man7/git-secret.7" - -# Building .deb package: -cd "$SCRIPT_DEST_DIR" && fpm -s dir -t deb \ - -a all \ - -n "$SCRIPT_NAME" \ - --epoch "$SCRIPT_EPOCH" \ - --version "$SCRIPT_VERSION" \ - --iteration "$SCRIPT_ITERATION" \ - --description="$SCRIPT_DESCRIPTION" \ - -C "$SCRIPT_DEST_DIR" \ - . diff --git a/utils/build-utils.sh b/utils/build-utils.sh new file mode 100644 index 00000000..b366de08 --- /dev/null +++ b/utils/build-utils.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +set -e + +# Initializing and settings: +READ_PEM=0644 +EXEC_PEM=0755 + +SCRIPT_NAME="git-secret" +SCRIPT_DESCRIPTION="A bash-tool to store your private data inside a git repository." +SCRIPT_VERSION=$(bash "${PWD}"/git-secret --version) + +# This might be overridden someday: +: "${SCRIPT_EPOCH:=0}" +: "${SCRIPT_ITERATION:=1}" + +# This may be overridden: +if [[ -z "$SCRIPT_BUILD_DIR" ]]; then + SCRIPT_BUILD_DIR="${PWD}/build" +fi + +SCRIPT_DEST_DIR="${SCRIPT_BUILD_DIR}/buildroot" + + +function locate_deb { + find "$SCRIPT_DEST_DIR" -maxdepth 1 -name "*.deb" | head -1 +} + + +function locate_rpm { + find "$SCRIPT_DEST_DIR" -maxdepth 1 -name "*.rpm" | head -1 +} + + +function preinstall_files { + # Preparing the files: + rm -rf "$SCRIPT_BUILD_DIR" + mkdir -p "$SCRIPT_DEST_DIR" + + # Coping the files inside the build folder: + install -D -T -b -m "$EXEC_PEM" -T "git-secret" "${SCRIPT_DEST_DIR}/usr/bin/git-secret" + install -m "$EXEC_PEM" -d "${SCRIPT_DEST_DIR}/usr/share/man/man1" + install -m "$EXEC_PEM" -d "${SCRIPT_DEST_DIR}/usr/share/man/man7" + for file in man/man1/* ; do + if [[ "$file" == *.ronn ]]; then + continue + fi + + install -D -T -b -m "$READ_PEM" -T "$file" "${SCRIPT_DEST_DIR}/usr/share/$file" + done + install -D -T -b -m "$READ_PEM" -T "man/man7/git-secret.7" \ + "${SCRIPT_DEST_DIR}/usr/share/man/man7/git-secret.7" +} + + +function build_package { + # Only requires `rpm` or `deb` as first argument: + local build_type="$1" + + # See https://github.com/jordansissel/fpm for docs: + fpm \ + -s dir \ + -t "$build_type" \ + -a all \ + -n "$SCRIPT_NAME" \ + --version "$SCRIPT_VERSION" \ + --description "$SCRIPT_DESCRIPTION" \ + --url "https://sobolevn.github.io/git-secret/" \ + --maintainer "Nikita Sobolev (mail@sobolevn.me)" \ + --license "MIT" \ + -C "$SCRIPT_DEST_DIR" \ + -d "git" \ + -d "gnupg" \ + --deb-no-default-config-files \ + . +} + + +function clean_up_files { + rm -rf "${SCRIPT_DEST_DIR:?}/usr" +} diff --git a/utils/deb/deb-build.sh b/utils/deb/deb-build.sh new file mode 100755 index 00000000..3c433b06 --- /dev/null +++ b/utils/deb/deb-build.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -e + +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/build-utils.sh" + +preinstall_files + +# Building .deb package: +cd "$SCRIPT_DEST_DIR" && build_package "deb" + +# Cleaning up: +clean_up_files && cd "${SECRET_PROJECT_ROOT}" diff --git a/utils/deb/deb-ci.sh b/utils/deb/deb-ci.sh new file mode 100644 index 00000000..571003b3 --- /dev/null +++ b/utils/deb/deb-ci.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -e + +# Note that this file is created for test purposes: +# 1. It runs inside the Docker container +# 2. It does not use `sudo` or anything +# 3. If you would like to install `.deb` package on your system, see `Installation` + +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/build-utils.sh" + +# This folder should contain just one .deb file: +DEB_FILE_LOCATION=$(locate_deb) + + +# Integration tests +function integration_tests { + # Installing the package: + dpkg -i "$DEB_FILE_LOCATION" + + # Configuring the dependencies: + apt-get -f -y install + + # Testing the installation: + dpkg --get-selections | grep "git-secret" + which "git-secret" + + # Test the manuals: + man --where "git-secret" # .7 + man --where "git-secret-init" # .1 +} + +integration_tests + +# Unit tests: +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/tests.sh" diff --git a/utils/deb/deb-deploy.sh b/utils/deb/deb-deploy.sh new file mode 100755 index 00000000..961468be --- /dev/null +++ b/utils/deb/deb-deploy.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -e + +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/build-utils.sh" + +# Variables, which will be used in `bintray.json`: +SCRIPT_VERSION=$(bash "${PWD}/git-secret" --version) +RELEASE_DATE=$(date +%Y-%m-%d) + +# add `\"override\": 1 \` into the `matrixParams`, if needed: +echo "{ \ + \"package\": { \ + \"name\": \"git-secret\", \ + \"repo\": \"deb\", \ + \"subject\": \"sobolevn\" \ + }, \ + \"version\": { + \"name\": \"${SCRIPT_VERSION}\", \ + \"desc\": \"Version ${SCRIPT_VERSION}\", \ + \"released\": \"${RELEASE_DATE}\", \ + \"vcs_tag\": \"v${SCRIPT_VERSION}\", \ + \"gpgSign\": true \ + }, \ + \"files\": [{ \ + \"includePattern\": \"build/buildroot/(.*\.deb)\", \ + \"uploadPattern\": \"/git-secret_${SCRIPT_VERSION}_all.deb\", \ + \"matrixParams\": { \ + \"deb_distribution\": \"stable\", \ + \"deb_component\": \"main\", \ + \"deb_architecture\": \"all\" \ + } \ + }], \ + \"publish\": true \ +}" > "${SECRET_PROJECT_ROOT}/build/deb_descriptor.json" diff --git a/utils/gh-branch.sh b/utils/gh-branch.sh index cf8a32db..06a9d92e 100755 --- a/utils/gh-branch.sh +++ b/utils/gh-branch.sh @@ -4,11 +4,14 @@ set -e function update_gh_branch { - local branch_name=$(git branch | grep '*' | sed 's/* //') - git checkout gh-pages + local branch_name + + branch_name=$(git branch | grep '\*' | sed 's/* //') + + git checkout 'gh-pages' make - git add _posts + git add '_posts' git commit -m 'documentation update' git checkout "$branch_name" } diff --git a/utils/post-commit.sh b/utils/hooks/post-commit.sh similarity index 62% rename from utils/post-commit.sh rename to utils/hooks/post-commit.sh index e07d0543..dff89cee 100755 --- a/utils/post-commit.sh +++ b/utils/hooks/post-commit.sh @@ -2,18 +2,18 @@ set -e -BRANCH_NAME=$(git branch | grep '*' | sed 's/* //') +BRANCH_NAME=$(git branch | grep '\*' | sed 's/* //') -if [[ "$BRANCH_NAME" == 'master' ]]; then +if [[ "$BRANCH_NAME" == 'staging' ]]; then # Build new web documentation: make build-gh-pages -fi - -if [[ "$BRANCH_NAME" == 'staging' ]]; then - # create new release: + + # Compare script version and the latest tag: NEWEST_TAG=$(git describe --abbrev=0 --tags) - SCRIPT_VERSION=$(bash ${PWD}/git-secret --version) + SCRIPT_VERSION=$(bash "${PWD}/git-secret" --version) + if [[ "$NEWEST_TAG" != "v${SCRIPT_VERSION}" ]]; then + # Create new release: git tag -a "v${SCRIPT_VERSION}" -m "version $SCRIPT_VERSION" fi fi diff --git a/utils/pre-commit.sh b/utils/hooks/pre-commit.sh similarity index 58% rename from utils/pre-commit.sh rename to utils/hooks/pre-commit.sh index 62c01a68..f14a52c7 100755 --- a/utils/pre-commit.sh +++ b/utils/hooks/pre-commit.sh @@ -2,15 +2,15 @@ set -e -BRANCH_NAME=$(git branch | grep '*' | sed 's/* //') +BRANCH_NAME=$(git branch | grep '\*' | sed 's/* //') -if [[ $BRANCH_NAME != '(no branch)' ]]; then +if [[ "$BRANCH_NAME" != '(no branch)' ]]; then unset GIT_WORK_TREE # Run tests: make test - if [[ $BRANCH_NAME == "master" ]]; then + if [[ "$BRANCH_NAME" == "staging" ]]; then # Build new manuals: make build-man diff --git a/utils/install.sh b/utils/install.sh index b328704b..fd8aedb2 100755 --- a/utils/install.sh +++ b/utils/install.sh @@ -1,16 +1,21 @@ #!/usr/bin/env bash + set -e + # Credit goes to: # https://github.com/sstephenson/bats/blob/master/install.sh -resolve_link() { +function resolve_link { $(type -p greadlink readlink | head -1) "$1" } -abs_dirname() { - local cwd="$(pwd)" +function abs_dirname { + local cwd local path="$1" + cwd="$(pwd)" + + while [ -n "$path" ]; do cd "${path%/*}" local name="${path##*/}" @@ -27,11 +32,16 @@ if [ -z "$PREFIX" ]; then exit 1 fi -SCRIPT_ROOT="$(dirname $(abs_dirname "$0"))" +SCRIPT_ROOT="$(dirname "$(abs_dirname "$0")")" mkdir -p "$PREFIX"/bin "$PREFIX"/share/man/man1 "$PREFIX"/share/man/man7 cp "$SCRIPT_ROOT"/git-secret "$PREFIX"/bin/git-secret -cp -R "$SCRIPT_ROOT"/man/man1/* "$PREFIX"/share/man/man1 + +# There was an issue with this line: +# cp -R "$SCRIPT_ROOT"/man/man1/* "$PREFIX"/share/man/man1 +# see https://github.com/sobolevn/git-secret/issues/35 for reference. +find "$SCRIPT_ROOT"/man/man1 -name '*.1' -print0 | xargs -0 -I {} cp \ + -a {} "$PREFIX"/share/man/man1 cp "$SCRIPT_ROOT"/man/man7/git-secret.7 "$PREFIX"/share/man/man7/git-secret.7 echo "Installed git-secret to ${PREFIX}/bin/git-secret" diff --git a/utils/make/make-ci.sh b/utils/make/make-ci.sh new file mode 100644 index 00000000..61441cb3 --- /dev/null +++ b/utils/make/make-ci.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -e + +# Note that this file is created for test purposes: +# 1. It runs inside the Docker container +# 2. It does not use `sudo` or anything +# 3. If you would like to install a package with `make` on your system, +# see `Installation` + + +# Integration tests +function integration_tests { + # Building the package: + make build + + # Installing the package: + make install + + # Testing the installation: + which "git-secret" + + # Test the manuals: + man --where "git-secret" # .7 + man --where "git-secret-init" # .1 +} + +integration_tests + +# Unit tests: +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/tests.sh" diff --git a/utils/rpm/rpm-build.sh b/utils/rpm/rpm-build.sh new file mode 100644 index 00000000..09434943 --- /dev/null +++ b/utils/rpm/rpm-build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e + +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/build-utils.sh" + +# Copying all the required files to the build directory: +preinstall_files + +# Building .rpm package: +cd "$SCRIPT_DEST_DIR" && build_package "rpm" + +# Cleaning up: +clean_up_files && cd "${SECRET_PROJECT_ROOT}" diff --git a/utils/rpm/rpm-ci.sh b/utils/rpm/rpm-ci.sh new file mode 100644 index 00000000..4bb7c4ac --- /dev/null +++ b/utils/rpm/rpm-ci.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -e + +# Note that this file is created for test purposes: +# 1. It runs inside the Docker container +# 2. It does not use `sudo` or anything +# 3. If you would like to install `.rpm` package on your system, see `Installation` + +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/build-utils.sh" + +# This folder should contain just one .rpm file: +RPM_FILE_LOCATION=$(locate_rpm) + + +# Integration tests +function integration_tests { + # Installing the package: + dnf install -y "$RPM_FILE_LOCATION" + + # Testing the installation: + dnf info "git-secret" + which "git-secret" + + # Test the manuals: + man --where "git-secret" # .7 + man --where "git-secret-init" # .1 +} + +integration_tests + +# Unit tests: +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/tests.sh" diff --git a/utils/rpm/rpm-deploy.sh b/utils/rpm/rpm-deploy.sh new file mode 100644 index 00000000..1fe69396 --- /dev/null +++ b/utils/rpm/rpm-deploy.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -e + +# shellcheck disable=SC1090,SC1091 +source "${SECRET_PROJECT_ROOT}/utils/build-utils.sh" + +# Variables, which will be used in `bintray.json`: +SCRIPT_VERSION=$(bash "${PWD}/git-secret" --version) +RELEASE_DATE=$(date +%Y-%m-%d) + +# add `\"override\": 1 \` into the `matrixParams`, if needed: +echo "{ \ + \"package\": { \ + \"name\": \"git-secret\", \ + \"repo\": \"rpm\", \ + \"subject\": \"sobolevn\" \ + }, \ + \"version\": { + \"name\": \"${SCRIPT_VERSION}\", \ + \"desc\": \"Version ${SCRIPT_VERSION}\", \ + \"released\": \"${RELEASE_DATE}\", \ + \"vcs_tag\": \"v${SCRIPT_VERSION}\", \ + \"gpgSign\": true \ + }, \ + \"files\": [{ \ + \"includePattern\": \"build/buildroot/(.*\.rpm)\", \ + \"uploadPattern\": \"/git-secret-${SCRIPT_VERSION}-1.noarch.rpm\" + }], \ + \"publish\": true \ +}" > "${SECRET_PROJECT_ROOT}/build/rpm_descriptor.json" diff --git a/utils/tests.sh b/utils/tests.sh new file mode 100755 index 00000000..eadf43b4 --- /dev/null +++ b/utils/tests.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# `SECRET_PROJECT_ROOT` must be set before running the script. + +set -e + +# Running all the bats-tests: +cd "${SECRET_PROJECT_ROOT}"; rm -rf temp; mkdir temp; cd temp; +bats "${SECRET_PROJECT_ROOT}/tests" diff --git a/utils/uninstall.sh b/utils/uninstall.sh new file mode 100644 index 00000000..fe54bc09 --- /dev/null +++ b/utils/uninstall.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e + + +PREFIX="$1" +if [ -z "$PREFIX" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# Binary: +rm -f "$PREFIX"/bin/git-secret + +# Manuals: +find "$PREFIX"/share/man/man1 -type f -name "git-secret-*.1" -exec rm -f {} \; +rm -f "$PREFIX"/share/man/man7/git-secret.7