📜 ⬆️ ⬇️

Universal work with VCS / SCM within the framework of automation with FutoIn CID

use cases


For some modern programmers, there are no version control systems other than Git, but in practice Subversion is still in demand, and Mercurial has its ardent supporters. Quick search in reinforcements.


As a result, DevOps of not single-project companies are faced with the need to automate work with very different systems. In this case, each has its own nuances and inevitably there are hidden errors in the scenarios that shoot at the most inopportune moment. There is a need for predictable behavior with minimal “flexibility” rather than a colorful bouquet of possibilities.


Interface


The article introducing the FutoIn CID has already described the implicit work with different VCS. In version v0.7, an explicit command interface and a new functionality were added to automate the creation and merging of branches:


In general, the interface itself with the comments below:


cid vcs checkout [<vcs_ref>] [--vcsRepo=<vcs_repo>] [--wcDir=<wc_dir>] cid vcs commit <commit_msg> [<commit_files>...] [--wcDir=<wc_dir>] cid vcs merge <vcs_ref> [--no-cleanup] [--wcDir=<wc_dir>] cid vcs branch <vcs_ref> [--wcDir=<wc_dir>] cid vcs delete <vcs_ref> [--vcsRepo=<vcs_repo>] [--cacheDir=<cache_dir>] [--wcDir=<wc_dir>] cid vcs export <vcs_ref> <dst_dir> [--vcsRepo=<vcs_repo>] [--cacheDir=<cache_dir>] [--wcDir=<wc_dir>] cid vcs tags [<tag_pattern>] [--vcsRepo=<vcs_repo>] [--cacheDir=<cache_dir>] [--wcDir=<wc_dir>] cid vcs branches [<branch_pattern>] [--vcsRepo=<vcs_repo>] [--cacheDir=<cache_dir>] [--wcDir=<wc_dir>] cid vcs reset [--wcDir=<wc_dir>] cid vcs ismerged <vcs_ref> [--wcDir=<wc_dir>] 

If we step back from the slogans about the ideological superiority of decentralized version control systems, then the bottom line in the development of any well-off project remains the same client-server model with additional buns on the client side. The second obvious point is the smooth "emulation" of the client-server model in distributed systems and the complexity of the implementation of the inverse. This is the reason for the logic of work - mandatory implicit synchronization with the server.


This implies the following correspondence table:


CIDGitMercurialSubversion
cid vcs checkoutgit clone/fetch + git checkouthg pull + hg checkoutsvn checkout/switch
cid vcs commitgit commit + git pushhg commit + hg pushsvn commit
cid vcs mergegit merge + git pushhg merge + hg pushsvn merge + svn commit
cid vcs branchgit checkout -b + git pushhg branch + hg pushsvn copy
cid vcs deletegit branch -D + git push -f --deletehg checkout + hg commit --close-branch + hg pushsvn remove
cid vcs exportgit fetch/clone --mirror --depth=1 + git archive | tar git archive | tarhg archive --type files + .hg* cleanupsvn export
cid vcs tagsgit ls-remotehg tagssvn ls {repo}/tags
cid vcs branchesgit ls-remotehg branchessvn ls {repo}/branches
cid vcs resetgit merge --abort + git reset --hardhg update --clean + hg purge -I **/*.origsvn revert -R .
cid vcs ismergedgit branch -r --merged HEADhg merge --previewsvn mergeinfo --show-revs eligible

It seems to be quite understandable for all the brevity. It is worth noting that:


  1. SVN relies on a merger with no explicit indication of revisions — know what you're doing.
  2. In Hg, there is no deletion of branches, and bookmarks look more like a crutch.
  3. Of course, at least on these three systems the world has come together with a wedge, it is possible to add support for any other through the plug-in mechanism.

Few examples


All examples without further ado: a small comment, a sequence of commands as it is, and a visual result.


> Preparatory work


Again we use pure Debian Jessie. Let's make a Git repository, add the file README.txt and LICENSE, make the second branch develop.


 sudo apt-get install -y python-pip sudo pip install futoin-cid VCS_REPO_DIR=${HOME}/repo VCS_REPO=git:${VCS_REPO_DIR} function prep_cache_dir() { local repo=$1 local cache_dir=$(echo $repo | sed -e 's,[/:@],_,g') [ -d $cache_dir ] && cid vcs reset --wcDir=$cache_dir 1>&2 echo $cache_dir } # set -x is too verbose function cid() { echo '$' cid "$@" 1>&2 $(which cid) "$@" } rm ${VCS_REPO_DIR} wc $(prep_cache_dir ${VCS_REPO}) -rf cid tool exec git -- init --bare ${VCS_REPO_DIR} cid vcs checkout --vcsRepo=${VCS_REPO} --wcDir=wc # Commit All echo 'Info' > wc/README.txt cid vcs commit 'Initial commit' --wcDir=wc # Commit specific file(s) echo 'License' > wc/LICENSE cid vcs commit 'Adding license' LICENSE --wcDir=wc cid vcs branch develop --wcDir=wc 

prepare


> Job Story â„–1: when work begins on a new feature, automatic branch creation is required to streamline the name


Note: it is assumed that the developers can not create branches on their own or this is not welcomed, and the trigger in some way works in the tracker.


 function on_feature_start() { local repo="$1" local feature="$2" local cache_dir=$(prep_cache_dir $repo) cid vcs checkout develop --vcsRepo=$repo --wcDir=$cache_dir cid vcs branch feature-${feature} --wcDir=$cache_dir } function list_branches() { # Remote case cid vcs branches --vcsRepo=${VCS_REPO} # Local case cid vcs branches --wcDir=wc } on_feature_start "${VCS_REPO}" '123_one' on_feature_start "${VCS_REPO}" '234_two' list_branches 

case #1


> Job Story â„–2: every night (every commit), you need to merge the develop (release) branch into the feature (develop) branch to avoid discrepancies and ensure that the process is respected


Note: this workflow is considered to be ideologically correct [and safe], although rebase makes a more sterile and understandable history.


Branch preparation:


 cid vcs checkout develop --wcDir=wc echo 'Info 2' > wc/README.txt cid vcs commit 'Commit 2' --wcDir=wc cid vcs checkout feature-234_two --wcDir=wc echo 'Info 3' > wc/README.txt cid vcs commit 'Conflict 3' --wcDir=wc 

case #2 prepare


 function sync_branches() { local repo="$1" local cache_dir=$(prep_cache_dir $repo) local logfile=$(realpath $2) cid vcs checkout develop --vcsRepo=$repo --wcDir=$cache_dir pushd $cache_dir # Release -> Develop echo >$logfile for b in $(cid vcs branches 'release*'); do echo -n "Merging $b into develop: " >>$logfile cid vcs merge $b && \ echo 'OK' >>$logfile || \ echo 'FAIL' >>$logfile done # Develop -> Feature for b in $(cid vcs branches 'feature*'); do echo -n "Merging develop into $b: " >>$logfile cid vcs checkout $b && \ cid vcs merge develop && \ echo 'OK' >>$logfile || \ echo 'FAIL' >>$logfile done popd } sync_branches "${VCS_REPO}" merge.log cat merge.log 

case #2


Error expected - we specifically created a conflict, but a typo in it - no. Will be fixed in the next release.


> Job Story â„–3: after release, delete all enabled feature branches so as not to clutter up the namespace


Note: for Hg and SVN there is nothing to worry at all, but for Git there is a risk of losing commits - therefore it is advisable to have a read-only mirror for the story.


 function remove_merged() { local repo="$1" local cache_dir=$(prep_cache_dir $repo) local logfile=$(realpath $2) cid vcs checkout develop --vcsRepo=$repo --wcDir=$cache_dir pushd $cache_dir echo >$logfile # Removed merged into develop for b in $(cid vcs branches 'feature*'); do if ! cid vcs ismerged $b; then continue fi echo -n "Removing $b: " >>$logfile cid vcs delete $b && \ echo 'OK' >>$logfile || \ echo 'FAIL' >>$logfile done popd } # Merge first branch cid vcs checkout develop --wcDir=wc cid vcs merge feature-123_one --wcDir=wc # Try cleanup remove_merged "${VCS_REPO}" delete.log cat delete.log 

case #3


> Job Story â„–4: at specified intervals, generate files and send to VCS in order to have a complete change history


Examples: a) downloadable files in a commercial blog or news site have a certain value, Subversion becomes extremely relevant to increase the integrity and efficiency of archiving b) an example of constantly updated black lists of addresses of active attacks , without the participation of FutoIn CID.


 function update_file() { local repo="$1" local cache_dir=$(prep_cache_dir $repo) cid vcs checkout develop --vcsRepo=$repo --wcDir=$cache_dir pushd $cache_dir date > Timestamp.txt cid vcs commit 'Updated timestamp' Timestamp.txt popd } update_file "${VCS_REPO}" 

case #4


> Job Story â„–5: every night, you need to update the dependencies in all projects to always use the current version


Note: there may be a bunch of other variations of automated processing of the list of projects.


 function update_project_deps() { local repo="$1" local cache_dir=$(prep_cache_dir $repo) cid vcs checkout develop --vcsRepo=$repo --wcDir=$cache_dir pushd $cache_dir date > Timestamp.txt for t in $(cid tool detect); do case $t in npm*|composer*|bundler*) cid tool exec $t -- update ;; esac done cid vcs commit 'Updated dependencies' popd } update_project_deps "${VCS_REPO}" 

case #5
No npm / composer / bundler files were added to the example in order not to clutter up.


Conclusion


In general, FutoIn CID does not impose any technological processes, but only provides a single lightweight interface to the VCS / SCM for the vast creative work of the admin, DevOps and even the developer on the command line.


Of course, the interface has not fully settled yet, backward compatible changes are possible. Any problems found, suggestions and suggestions are welcome .


')

Source: https://habr.com/ru/post/326928/


All Articles