Skip to content

Commit

Permalink
Pull request for #126: Fix lingering issues with release.py (#127)
Browse files Browse the repository at this point in the history
* #126 hit all checks, no documentation

* #126 fix overwrite of scons_local_path

* #126 docs

* #127 #126 small readme changes for PR

* #126 small fixes

* #127 #126 abstract text search, better config checks

* #127 #126 search dir not output for SConstruct
  • Loading branch information
arosenbe authored Sep 6, 2017
1 parent e3fe833 commit 53d4026
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 27 deletions.
3 changes: 3 additions & 0 deletions gslab_scons/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ For example, to automatically release to Dropbox set
release_directory: /Users/you/Dropbox/release
```
Before releasing, the module executes an SCons dry run to check that your build is up-to-date.
By default, we run SCons from `run.py`, but you can specify another script through `scons_local_path=<relative path to script here>`. Set this argument to `None` or `False` if you want to run `scons` using your global installation.

Including the option `no_zip` will prevent files
from being zipped before they are released to the specified location.

Expand Down
52 changes: 32 additions & 20 deletions gslab_scons/_release_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,37 +176,38 @@ def upload_asset(github_token, org, repo, release_id, file_name,
return r.content


def up_to_date(mode = 'scons', directory = '.'):
def up_to_date(mode = 'scons', directory = '.', scons_local_path = None):
'''
If mode = scons, this function checks whether the targets of a
directory run using SCons are up to date.
If mode = git, it checks whether the directory's sconsign.dblite has
changed since the latest commit.
If mode = git, it checks whether the directory's working tree is clean.
'''
if mode not in ['scons', 'git']:
raise ReleaseError("up_to_date()'s mode argument must be "
"'scons' or 'git")
"'scons' or 'git'")

original_directory = os.getcwd()
os.chdir(directory)

if mode == 'scons':
# If mode = scons, conduct a dry run to check whether
# all targets are up-to-date
command = 'scons ' + directory + ' --dry-run'
if scons_local_path is not None:
scons_installation = 'python %s ' % os.path.join(directory,
scons_local_path)
else:
scons_installation = 'scons '
command = scons_installation + directory + ' --dry-run'
else:
# If mode = git, check whether .sconsign.dblite has changed
# since the last commit.
original_directory = os.getcwd()
os.chdir(directory)
# If mode = git, check whether the working tree is clean.
command = 'git status'

logpath = '.temp_log_up_to_date'

with open(logpath, 'wb') as temp_log:
subprocess.call(command, stdout = temp_log,
stderr = temp_log, shell = True)

stderr = temp_log, shell = True)
with open(logpath, 'rU') as temp_log:
output = temp_log.readlines()
os.remove(logpath)
Expand All @@ -219,31 +220,42 @@ def up_to_date(mode = 'scons', directory = '.'):
# argument is actually a SCons directory.
# We use the fact that running scons outside of SCons directory
# produces the message: "No SConstruct file found."
if [True for out in output if re.search('No SConstruct file found', out)]:
raise ReleaseError('up_to_date(mode = scons) must be run on a '
if not os.path.isfile('SConstruct'):
raise ReleaseError('up_to_date(mode = scons) must be run on an '
'SCons directory.')
# Next determine if SCons could start to run.
# We use the fact that our SCons notifies when it starts the build process.
elif not check_list_for_regex('scons: Reading SConscript files', output):
raise ReleaseError('up_to_date(mode = scons) must be able to begin '
'SCons build process.')

# If mode = scons, look for a line stating that the directory is up to date.
result = [True for out in output if re.search('is up to date\.$', out)]
result = check_list_for_regex('is up to date\.$', output)

else:
# Determine whether the directory specified as a function
# argument is actually a git repository.
# We use the fact that running `git status` outside of a git directory
# produces the message: "fatal: Not a git repository"
if [True for out in output if re.search('Not a git repository', out)]:
if check_list_for_regex('Not a git repository', output):
raise ReleaseError('up_to_date(mode = git) must be run on a '
'git repository.')

# If mode = git, look for a line stating that sconsign.dblite has changed
# If mode = git, look for a line stating that nothing has changed
# since the latest commit.
result = [out for out in output if re.search('sconsign\.dblite', out)]
result = [True for out in result if re.search('modified', out)]
result = not bool(result)
result = check_list_for_regex('nothing to commit, working tree clean', output)

os.chdir(original_directory)

# Return the result.
return bool(result)
return result


def check_list_for_regex(regex, l):
'''
True if any successful re.search for text in elements of list. False otherwise.
'''
return bool([True for entry in l if re.search(regex, entry)])


def extract_dot_git(path = '.git'):
Expand Down
2 changes: 1 addition & 1 deletion gslab_scons/provenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def write_readme(readme_path, provenance_path):
with open(readme_path, 'rU') as f:
out = '%s' % f.read()
except IOError:
raise IOError(('Cannot read %s.\n If you are in release mode,' % readme_path) +
raise IOError(('Cannot read %s.\n If you are in release mode, ' % readme_path) +
'please specify the command line argument param `readme=<README_PATH>`.' )

with open(provenance_path, 'ab') as f:
Expand Down
26 changes: 20 additions & 6 deletions gslab_scons/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ def main(version = None,
prov_excluded_dirs = [],
external_provenance = [],
dont_zip = False,
readme = None):
inspect_repo()
readme = None,
scons_local_path = 'run.py'):

# Check if user specified a scons_local_path
if scons_local_path == 'run.py':
check_none = lambda scons_local_path, regex: bool(re.match(regex, scons_local_path, re.IGNORECASE))
try:
scons_local_path = next(arg for arg in sys.argv if re.search('^scons_local_path=', arg))
scons_local_path = re.sub('^scons_local_path=', '', scons_local_path)
if check_none(scons_local_path, 'None') or check_none(scons_local_path, 'False'):
scons_local_path = None
except:
pass
inspect_repo(scons_local_path = scons_local_path)

# Extract information about the clone from its .git directory
try:
Expand Down Expand Up @@ -100,14 +112,16 @@ def main(version = None,
provenance_path = provenance_path)


def inspect_repo():
def inspect_repo(scons_local_path = None):
'''Ensure the repo is ready for release.'''
if not _release_tools.up_to_date(mode = 'scons'):
if not _release_tools.up_to_date(mode = 'scons', scons_local_path = scons_local_path):
raise ReleaseError('SCons targets not up to date.')
elif not _release_tools.up_to_date(mode = 'git'):
print "Warning: `scons` has run since your latest git commit.\n"
warn = "Warning: your git working tree is not clean.\n" \
+ "End this process and run `git status` for more information."
print warn
response = raw_input("Would you like to continue anyway? (y|n)\n")
if response in ['N', 'n']:
if response in ['N', 'n']:
sys.exit()


Expand Down

0 comments on commit 53d4026

Please sign in to comment.