From 556e7e5e230e91f57dadf14a63e17e9b614220e0 Mon Sep 17 00:00:00 2001 From: Gregory Ballantine Date: Sun, 4 Apr 2021 01:46:14 -0400 Subject: [PATCH] Added version pinning support with git tags --- README.md | 6 ++- lib/Formula.py | 24 +++++++----- lib/FormulaRepo.py | 85 ++++++++++++++++++----------------------- salt-formula-manager.py | 10 ++--- sfm.yaml.example | 8 +--- 5 files changed, 62 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 049dc0f..2346504 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,11 @@ Each formula listed (as noted above) has specific options that may be set to cha The remote URL to use - theoretically, this should work with SSH URLs if you have permission to clone over SSH, otherwise, HTTPS URLs will work just fine if you have permission to access the repository. -#### `git_branch` +#### `version` -This defines a specific Git branch to track for changes, if the formula is not on said branch, SFM will attempt to checkout the desired branch. +**REQUIRED!** This defines a specific Git TAG to track, if the formula is not on said tag, SFM will attempt to checkout the desired tag. + +**Note:** This currently only supports git tags! Future support for using commit hashes and branch names is planned. #### `name` diff --git a/lib/Formula.py b/lib/Formula.py index d6ff2dd..63b9c56 100644 --- a/lib/Formula.py +++ b/lib/Formula.py @@ -4,6 +4,7 @@ class Formula(): # class variables git_url = '' + version = '' local_path = '' # class constructor @@ -17,6 +18,7 @@ class Formula(): def __parse_entry(self): # define our function variables here git_url = '' + version = '' local_path = '' # check if the formula entry is a string or a dictionary @@ -33,25 +35,27 @@ class Formula(): git_url = str(self.formula_def['url']) else: git_url = str(self.formulas_url) + str(self.formula_def['name']) + + # check if the git tag was defined + if 'version' in self.formula_def: + version = str(self.formula_def['version']) + else: + # this is incorrect! + print('You must define a version tag for every formula (issue is: ' + str(self.formula_def) + ')') + sys.exit(1) # put together the local local_path = str(self.formulas_dir) + '/' + str(self.formula_def['name']) - elif isinstance(self.formula_def, str): - # entry is a string - git_url = str(self.formulas_url) + str(self.formula_def) + '-formula' - local_path = str(self.formulas_dir) + '/' + str(self.formula_def) + '-formula' else: # entry type is not supported - print('One of your formula entries is not a dict or a string (' + str(self.formula_def) + ') - please fix this.') + print('One of your formula entries is not a dict (' + str(self.formula_def) + ') - please fix this.') sys.exit(1) # set the class values here self.git_url = git_url + self.version = version self.local_path = local_path - # checks to see if a branch, tag, or commit to track has been defined + # checks to see if a tag to track has been defined def get_tracking_state(self): - if 'git_branch' in self.formula_def: - return self.formula_def['git_branch'] - else: - return False + return self.version diff --git a/lib/FormulaRepo.py b/lib/FormulaRepo.py index c92c02f..92b8142 100644 --- a/lib/FormulaRepo.py +++ b/lib/FormulaRepo.py @@ -13,48 +13,39 @@ class FormulaRepo(): # class constructor def __init__(self, formula): self.repo_url = formula.git_url + self.version = formula.version self.repo_path = formula.local_path # sets up our class' repo instance def __bake(self): self.repo = sh.git.bake(_cwd=self.repo_path) - # list of git branches - def get_branches(self): - # define our branch array - branches = [] - # fetch output of git branches - branch_lines = self.repo.branch() - # loop through the branches - for line in branch_lines: + # list of git tags + def get_tags(self): + # define our tag array + tags = [] + # fetch output of git tags + tag_lines = self.repo.tag() + # loop through the tags + for line in tag_lines: bits = Utils.remove_ansi_from_list(line.split()) - # check if the branch was marked as current + # check if the tag was marked as current if bits[0] == '*': - branches.append(bits[1]) + tags.append(bits[1]) else: - branches.append(bits[0]) + tags.append(bits[0]) - # return our list of branch names - return branches + # return our list of tag names + return tags - # get current branch - def get_current_branch(self): - branches = self.repo.branch() - # loop through the branches - for line in branches: - bits = Utils.remove_ansi_from_list(line.split()) - # check for if a branch is listed as current - if bits[0] == '*': - # return the branch name - return bits[1] + # get current tag + def get_current_version(self): + return self.repo.describe('--tags').strip() - # return false if no branch is selected - return False - - # switch to branch - def switch_branch(self, branch): - print('Switching %s to the \'%s\' branch' % (self.repo_path, branch)) - self.repo.checkout(branch) + # switch to tag + def switch_version(self, version): + print('Switching %s to the \'%s\' tag' % (self.repo_path, version)) + self.repo.checkout('tags/' + version) # retrieves repo from remote location def retrieve(self): @@ -71,28 +62,26 @@ class FormulaRepo(): self.__bake() # check if the repo is up to date - def check_tracking_info(self, branch): - if branch != False: - # tracking a specific branch on the repo - # check to make sure that the given branch name actually exists first - if not branch in self.get_branches(): - print('%s is not an existing branch name for %s - please fix this.' % (branch, self.repo_path)) - sys.exit(1) + def check_tracking_info(self, version): + # tracking a specific tag on the repo + # check to make sure that the given tag name actually exists first + if not version in self.get_tags(): + print('%s is not an existing tag name for %s - please fix this.' % (version, self.repo_path)) + sys.exit(1) - repo_branch = self.get_current_branch() - # check to make sure that the current tracked branch is, in fact, what we want - if branch != repo_branch: - self.switch_branch(branch) + repo_tag = self.get_current_version() + print(version) + print(repo_tag) + # check to make sure that the current tracked tag is, in fact, what we want + if version != repo_tag: + self.switch_version(version) - # let the user know which branch we're using - print('For %s, we\'re using the \'%s\' branch.' % (self.repo_path, branch)) - else: - # no branch was specified, so we're going with what's there - print('Using the default/current branch for %s' % (self.repo_path)) + # let the user know which tag we're using + print('For %s, we\'re using the \'%s\' tag.' % (self.repo_path, version)) # pull any new updates for the repo def pull_updates(self): print('Pulling updates for %s.' % self.repo_path) - # git pull - self.repo.pull() + # git fetch + self.repo.fetch() diff --git a/salt-formula-manager.py b/salt-formula-manager.py index c5528cd..6ab455e 100644 --- a/salt-formula-manager.py +++ b/salt-formula-manager.py @@ -43,14 +43,14 @@ def get_formulas(formulas, formulas_dir, formulas_url): # retrieve our formula formula_repo.retrieve() - # get the repo tracking information from the formula definition - tracking_branch = formula.get_tracking_state() - # make sure our formula's repo is up-to-date with the latest tracked version - formula_repo.check_tracking_info(tracking_branch) - # pull any new commits for the repo formula_repo.pull_updates() + # get the repo tracking information from the formula definition + tracking_version = formula.get_tracking_state() + # make sure our formula's repo is up-to-date with the latest tracked version + formula_repo.check_tracking_info(tracking_version) + # purge un-managed formulas def clean_formulas(conf): if conf['purge_formulas']: diff --git a/sfm.yaml.example b/sfm.yaml.example index 27652ae..0f84820 100644 --- a/sfm.yaml.example +++ b/sfm.yaml.example @@ -9,11 +9,7 @@ formulas_dir: formulas # remove unmanaged formulas purge_formulas: true -# list of formulas to import +# list of formulas to import; requires a version tag (currently only git tags for now) formulas: - vim - - users - - - example: - name: example-formula - url: https://git.example.com/user/salt-example + version: v0.15.4