Coder Social home page Coder Social logo

punch's Introduction

Punch

Build Status Version

Update your version while having a drink

Full documentation available at http://punch.readthedocs.io/en/latest/

About punch

Punch is a configurable version updater, and you can use to automate the management of your project's version number.

Punch stores the version of your project in its own file. Each time you need to update it, Punch runs through the configured files and replaces the old version with the new one. Additionally, Punch may also automatically commit the version change on your VCS of choice.

This project has been heavily inspired by bumpversion, and I want to thank Filip Noetzel, the author of that project for his work and the inspiring ideas.

Installation

Punch is available for both Python 2 and Python 3 through pip. Just create a virtual environment and run

pip install punch.py

To start working with Punch you need a configuration file and a version file. You may ask Punch to create the two files for you with reasonable starting values with the flag --init

punch --init

which will create the punch_config.py and punch_version.py files in the current directory.

Contributing

See the CONTRIBUTING file for detailed information. Please remember that this project is actively developed in the develop branch, so be sure to work there if you try to implement new feature of fix bugs.

punch's People

Contributors

ferndot avatar gthank avatar h4 avatar jobec avatar lgiordani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

punch's Issues

Possible typo in docs

I am not sure but there might be a typo in docs/index.md.

Section 'config file'
2nd paragraph
2nd sentence
'config_version' instead of 'config_file'

Cheers, Daniel

Build action doesn't properly compare date version parts to integer version parts

I still have some issues with the build action implemented in #14. Take the following config:

__config_version__ = 1

GLOBALS = {
    'serializer': '{{year}}.{{month}}.{{build}}',
}

FILES = ['setup.py']

VERSION = [
    {
        'name': 'year',
        'type': 'date',
        'fmt': 'YYYY'
    },
    {
        'name': 'month',
        'type': 'date',
        'fmt': 'MM'
    },
    {
        'name': 'build',
        'type': 'integer',
        'start_value': 0
    }
]

VCS = {
    'name': 'git',
    'commit_message': "Release {{ new_version }}",
}

ACTIONS = {
    'build': {
        'type': 'conditional_reset',
        'field': 'build',
        'update_fields': ['year', 'month']
    }
}

And the following version file:

year = 2017
month = 6
build = 8

When I simulate a build action, the new version is '2017.6.0'. The reason for this is this condition in the action module:

    if new_version == version:
        reset_part.inc()
    else:
        reset_part.reset()

Here new_version and version are considered different, even though they both point at 2017.6.8. The problem is that the new_version points at '2017', '6', 8. While the version points at 2017, 6, 8. That is, the types of the fields are not equal. The new_version contains integers and strings, while the old version contains only integers.

So there should probably be some normalisation.

Is there the ability to access previous version info in replacement template?

TL;DR -- I'd like to be able to add an "Unreleased" section at the top of a CHANGELOG.md file when I increment a "-dev" part.
I think that I have a small change that should do it, but Jinja complains about it. Perhaps there's a way to make Jinja happy or perhaps there's a better solution to my problem?


I'm using the technique described in the Complex Serializers section of the Advanced page to replace an "Unreleased" string with a version number in my CHANGELOG.md.

I'm also using a variant of the ""/alpha/beta technique described in the SemVer with prerelease metadata section of the examples page to manage a -dev suffix for the version info.

If I were able to access the previous version information in the replacement template, then I could insert a new blank section at the top of the CHANGELOG.md when I bump the dev part from "" to "dev".

The flow would go something like:

  • current contents of the CHANGELOG.md

    # Unreleased
    
    - new feature
    - another new feature
    
  • run punch --part minor, changes CHANGELOG.md to

    # 1.3.0
    
    - new feature
    - another new feature
    
  • run punch --part dev (which adds -dev to the version info in other files), which updates the CHANGELOG.md to:

    # Unreleased
    
    # 1.3.0
    
    - new feature
    - another new feature
    

I think it would work with a search rule that just searches the current version (including the # ) and a replacement template like:

'''
# Unreleased

# {{prev.major}}.{{prev.minor}}.{{prev.patch}} -- {{prev.year}}-{{prev.month}}-{{prev.day}}
'''

I've played around with a diff like so:

diff --git a/punch/cli.py b/punch/cli.py
index 84badfd..e5c20f7 100644
--- a/punch/cli.py
+++ b/punch/cli.py
@@ -310,9 +310,11 @@ def main(original_args=None):
             exc
         )

+    new_values=new_version.as_dict()
+    new_values.update({"prev": current_version.as_dict()})
     changes = global_replacer.run_all_serializers(
         current_version.as_dict(),
-        new_version.as_dict()
+        new_values
     )

     if args.verbose:

but I'm ending up with:

Traceback (most recent call last):
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/bin/punch", line 8, in <module>
    sys.exit(main())
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/punch/cli.py", line 316, in main
    changes = global_replacer.run_all_serializers(
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/punch/file_updater.py", line 37, in update
    new_version
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/punch/replacer.py", line 88, in replace
    new_version_dict
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/punch/replacer.py", line 78, in run_all_serializers
    name, current_version_dict, new_version_dict)
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/punch/replacer.py", line 63, in run_serializer
    replace_template.render(**new_version_dict)
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 3, in top-level template code
  File "/local_scratch/george.hartzell/tmp/ngs-ingress/.venv/lib/python3.7/site-packages/jinja2/environment.py", line 471, in getattr
    return getattr(obj, attribute)
jinja2.exceptions.UndefinedError: 'prev' is undefined

Any suggestions to get me unstuck, or alternate ways of reaching my goal?

Allow to replace fixed string by version

During development, in my documentation, I collect all changes along the way under a section called next release. With every release, I rename next release to the new version.

Currrently though, that's seems not to be possible, and I need to manually replace that heading. Causing me to frequently forget about it ๐Ÿ™ˆ

So, something like this would be useful:

GLOBALS = {
    'serializer': ["next release", "{{year}}.{{month}}.{{day}}"],
}

Don't overwrite other parts of the punch_version.py file

Hey!

First of all, thanks for creating this great tool. I've been successfully using it for a while.

I have a small request, namely, to stop overwriting the whole punch_version.py file after performing a version bump.

The reason I would like this is that I would like to have a comment at the top of punch_version.py explaining what this file is and where to find more information since this file is usually in a repository's top-level directory and developers/users will frequently see it and wonder what it is and what it does.

Here is an example punch_version.py I would like to have (and retain after bumping):

# Punch version file.

# It contains the current version of the project.

# For more information, see: https://punch.readthedocs.io/.

major = 0
minor = 4
patch = 0

Full example/reproducer:

punch --version
cat << EOF > punch_config.py
# Punch configuration file.

# For more information, see: https://punch.readthedocs.io/.

__config_version__ = 1

GLOBALS = {
    'serializer': {
        'semver': '{{ major }}.{{ minor }}.{{ patch }}',
     }
}

# NOTE: The FILES list is not allowed to be empty, so we need to pass it at
# least a single valid file.
FILES = ["README.md"]

VERSION = ['major', 'minor', 'patch']

EOF
touch README.md
cat << EOF > punch_version.py
# Punch version file.

# It contains the current version of the project.

# For more information, see: https://punch.readthedocs.io/.

major = 0
minor = 4
patch = 0
EOF
punch --part minor
cat punch_version.py

And the output I get:

punch [tadej@toronto Punch]$ punch --version
Punch version 2.0.0
Copyright (C) 2016 Leonardo Giordani
This is free software, see the LICENSE file.
Source: https://github.com/lgiordani/punch
Documentation: http://punch.readthedocs.io/en/latest/
punch [tadej@toronto Punch]$ cat << EOF > punch_config.py
> # Punch configuration file.
> 
> # For more information, see: https://punch.readthedocs.io/.
> 
> __config_version__ = 1
> 
> GLOBALS = {
>     'serializer': {
>         'semver': '{{ major }}.{{ minor }}.{{ patch }}',
>      }
> }
> 
> # NOTE: The FILES list is not allowed to be empty, so we need to pass it at
> # least a single valid file.
> FILES = ["README.md"]
> 
> VERSION = ['major', 'minor', 'patch']
> 
> EOF
punch [tadej@toronto Punch]$ touch README.md
punch [tadej@toronto Punch]$ cat << EOF > punch_version.py
> # Punch version file.
> 
> # It contains the current version of the project.
> 
> # For more information, see: https://punch.readthedocs.io/.
> 
> major = 0
> minor = 4
> patch = 0
> EOF
punch [tadej@toronto Punch]$ punch --part minor
Warning: Cannot find any match for version {'major': 0, 'minor': 4, 'patch': 0} in file README.md
punch [tadej@toronto Punch]$ cat punch_version.py
major = 0
minor = 5
patch = 0

no quotes when saving values from value_list

I'm testing out the punch tool for my project. I'm getting a syntax errors when trying to bump a version for the "SemVer with prerelease metadata" example. I'm using a windows box running version 1.4.0 of punch.py installed via pip.

Example with 'prerelease =' in punch_config.py.

PS C:\Users\james\Documents\test> punch --part patch
Traceback (most recent call last):
File "C:\Python27\Scripts\punch-script.py", line 11, in
load_entry_point('punch.py==1.4.0', 'console_scripts', 'punch')()
File "c:\python27\lib\site-packages\punch\cli.py", line 149, in main
current_version = ver.Version.from_file(args.version_file, config.version)
File "c:\python27\lib\site-packages\punch\version.py", line 79, in from_file
version_module = import_file(version_filepath)
File "c:\python27\lib\site-packages\punch\helpers.py", line 8, in import_file
module = imp.load_source("punch_config", filepath)
File "punch_version.py", line 4
prerelease =
^
SyntaxError: invalid syntax

Example with 'prerelease = alpha' in punch_config.py.

Traceback (most recent call last):
File "C:\Python27\Scripts\punch-script.py", line 11, in
load_entry_point('punch.py==1.4.0', 'console_scripts', 'punch')()
File "c:\python27\lib\site-packages\punch\cli.py", line 149, in main
current_version = ver.Version.from_file(args.version_file, config.version)
File "c:\python27\lib\site-packages\punch\version.py", line 79, in from_file
version_module = import_file(version_filepath)
File "c:\python27\lib\site-packages\punch\helpers.py", line 8, in import_file
module = imp.load_source("punch_config", filepath)
File "punch_version.py", line 4, in
prerelease = alpha
NameError: name 'alpha' is not defined

Now if I add quotes around alpha it works until I tried it a second time. It gets written without any quotes.

Thanks!

punch silently adds and commits unrelated untracked files to git

Punch version 1.4.2
os: Gentoo Linux
git version 2.16.2

$ git init
Initialized empty Git repository in /tmp/punch-bug/.git/
$ punch --init

...configure files and punch once...

$ cat punch_config.py
__config_version__ = 1

GLOBALS = {
    'serializer': '{{major}}.{{minor}}.{{patch}}',
}

FILES = ["VERSION"]

VERSION = ['major', 'minor', 'patch']

VCS = {
    'name': 'git',
    'commit_message': "Version updated from {{ current_version }} to {{ new_version }}",
}
$ cat punch_version.py
major = 0
minor = 2
patch = 0
$ cat VERSION
0.2.0
$ git status
On branch master
nothing to commit, working tree clean
$ touch a
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        a

nothing added to commit but untracked files present (use "git add" to track)
$ punch -p minor
$ git status
On branch master
nothing to commit, working tree clean
$ git log -n1 -p
commit 7c975201be6ec6a070d4f11d64df6e296c9ffd33 (HEAD -> master, tag: 0.3.0)
Author: Kyrylo Shpytsya <[email protected]>
Date:   Tue Feb 27 22:40:38 2018 +0200

    Version updated from 0.2.0 to 0.3.0

diff --git a/VERSION b/VERSION
index 0ea3a94..0d91a54 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.2.0
+0.3.0
diff --git a/a b/a
new file mode 100644
index 0000000..e69de29
diff --git a/punch_version.py b/punch_version.py
index 1085779..31aa2c8 100644
--- a/punch_version.py
+++ b/punch_version.py
@@ -1,3 +1,3 @@
 major = 0
-minor = 2
+minor = 3
 patch = 0

Observe the untracked file a being silently added and committed.

simulation, not existing file

If a file is renamed, the simulation shows everything ok but if punch is executed it fails.
Therefore a check would be great.
If the check shows that the file is not existing, no file should be updated otherwise it will become inconsistent.
And it should also be shown within the simulation.

Error in documentation

There is an error in the documentation of the command line switches. The "-S" option is not formatted.
The "Resets the folowing parts" sentence shall be corrected.

version regex match to IP addr

Hi,
in my code checker.py I have:

__version__ = '0.1.2'

class Checker():
    def __init__(self):
        self.ran = Bss(addr='10.0.1.2')

punch_config.py:

__config_version__ = 1
GLOBALS = {
    'serializer': '{{major}}.{{minor}}.{{patch}}',
}
FILES = ['checker.py', 'setup.py']
VERSION = ['major', 'minor', 'patch']

punch_version.py:

major = 0
minor = 1
patch = 2

When I run:

# punch -p patch

addr parameter will be change to 10.0.1.3, what is of course is unacceptable.
Is there any workaround of solution for it?

Of course I can review all changes before commit, but lately I miss one place and spent 2h with debugger to find out, that punch did it ;)

punch not compiled to exe on windows

When installing punch via pip on windows, there is no executable in the Scripts directory. Hence you cannot just run

punch --init

You need to run something like this to get it working.

python .venv\Scripts\punch --init

Cannot create a release with 1.4.3

The latest release seems to have broken punch.py for us.

Running punch --action build fails as follows:

Traceback (most recent call last):
  File "/Users/denis/.virtualenvs/onegov/bin/punch", line 11, in <module>
    sys.exit(main())
  File "/Users/denis/.virtualenvs/onegov/lib/python3.6/site-packages/punch/cli.py", line 295, in main
    uc.finish_release()
  File "/Users/denis/.virtualenvs/onegov/lib/python3.6/site-packages/punch/vcs_repositories/git_repo.py", line 99, in finish_release
    self._run(command_line)
  File "/Users/denis/.virtualenvs/onegov/lib/python3.6/site-packages/punch/vcs_repositories/vcs_repo.py", line 65, in _run
    raise RepositorySystemError(error_message)
punch.vcs_repositories.exceptions.RepositorySystemError: An error occurred executing 'git commit -m Release 2018.3.15':
Process output was: On branch 2018.3.15
Changes not staged for commit:
	modified:   punch_version.py
	modified:   setup.py

no changes added to commit

This seems to happen because the files are no longer added due to this change:
1cc1754

What's the reason for this being commented out?

pip install punch

Looks like there's something fishy going on here:

; pip install punch
Collecting punch
Requirement already satisfied (use --upgrade to upgrade): webob in /home/usr/.virtualenvs/widle/lib/python2.7/site-packages (from punch)
Installing collected packages: punch
Successfully installed punch-0.0.1

and

; pip uninstall punch
Uninstalling punch-0.0.1:
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/DESCRIPTION.rst
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/INSTALLER
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/METADATA
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/RECORD
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/WHEEL
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/metadata.json
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch-0.0.1.dist-info/top_level.txt
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch/__init__.py
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch/__init__.pyc
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch/app.py
  /home/usr/.virtualenvs/widle/lib/python2.7/site-packages/punch/app.pyc
Proceed (y/n)? y
  Successfully uninstalled punch-0.0.1

Add 'remove' action and multiple actions in sequence

I'd like for punch to support this workflow:

'serializer': "{{date}}.{{build}}{{'b{}'.format(beta) if beta}}"
VERSION = [
    {
        'name': 'date',
        'type': 'date',
        'fmt': '%Y%m%d'
    },
    {
        'name': 'build',
        'type': 'integer',
        'start_value': 1
    },
    {
        'name': 'beta',
        'type': 'integer',
        'start_value': 0
    }
]

And then I'd like to have two actions:

  • release
    • refresh date
    • conditional reset/increment build
    • set beta = None
  • beta
    • refresh date
    • conditional reset/increment build
    • conditional reset/increment beta

I propose to implement it like this:
Extend conditional_reset with a fields key, (field xor fields must be present). It behaves as field but checks multiple fields in order.
eg

        'type': 'conditional_reset',
        'fields': ['build', 'beta],
        'update_fields': ['date']
    },

Add remove action that sets a part to None
eg

'type': 'remove',
'field': 'beta'

Add a multi action that runs multiple other action types in sequence
eq

'type': 'multi',
'actions': [
  {'type': 'conditional_reset',
   'field': 'build'
   'update_fields': ['date']},
  {'type': 'remove',
   'field': 'beta'}]

Would you accept a PR implementing that design? Any feedback on the approach?

--runslow randomly fails on Travis CI

If I turn the --runslow option on (which just runs slower tests that use subprocess to run git and git-flow) Travis randomly experience failures, due to a lock file in the .git directory. I suspected that Travis reused old directories, but explicitly cleaning the temporary directories doesn't change the result.

--runslow is temporary deactivated, the tests pass in a local environment, but I would like to understand and fix this issue.

Automatically increment the date part

I'm using punch to build a package which includes a month part in its version number. Basically we do major.month.build.

For this I created the following config:

__config_version__ = 1

GLOBALS = {
    'serializer': '{{year}}.{{month}}.{{build}}',
}

FILES = ['setup.py']

VERSION = [
    {
        'name': 'year',
        'type': 'date',
        'fmt': 'YY'
    },
    {
        'name': 'month',
        'type': 'date',
        'fmt': 'MM'
    },
    {
        'name': 'build',
        'type': 'integer',
        'start_value': 0
    }
]

VCS = {
    'name': 'git',
    'commit_message': "Release {{ new_version }}",
}

However, I noticed that the month part of the build will only update if I explicitly say so. That is, to create a new build at the beginning of the month I need to do the following:

punch --part month

While during the month I need to run:

punch --part build

In other words, I need to manually roll the month version over. Is there an option to always do this automatically? I would expect a date version part to automatically change when the date changes.

October stripped wrongly

The month October gets stripped from 10 to 1 when using in the format MM. Seems like an lstrip is needed instead of a strip in strftime.

Print a warning when no match is found in controlled files

I came across an issue where I git reset --hard origin/master on a branch which had changes to files listed in FILES, and then running punch after that only updates punch_version.py, and doesn't update the files. I'm wondering if it's using modification time or some other stat on the files to skip updating?

Add ability to print project's current version to stdout

I have some tooling in a project that needs to obtain the project's current version as defined in Punch's version file.

Currently, I need to do something like:

python3 -c "exec(open('punch_version.py').read()); print('{}.{}.{}'.format(major, minor, patch))"

Having an argument, e.g. punch --print, would make things simpler.

Jinja2 missing

The jinja2 and six packages are not installed when issuing pip install punch.py

[git VCS] Additional branch options

It would be great if the git VCS could support the following:

  • Custom base branch:
    • Sometimes, releases need to be merged to a different branch than master
  • Auto merge disabling with make_release_branch enabled:
    • Allows one to make changes, e.g. HISTORY.rst before finishing a release
    • Status checks (CI, coverage, etc) on protected branches block direct merges

UnicodeDecodeError on UTF-8 character.

There is a problem with files that contain UTF-8 character. Create a file called version.txt (which punch has defined in FILES) which contains:

# โš  <- this causes the stack trace.
0.5.1

then run punch --part patch to get this trace:

Traceback (most recent call last):
  File "/home/usr/.virtualenvs/intranet/bin/punch", line 205, in <module>
    updater.update(current_version.as_dict(), new_version.as_dict())
  File "/home/usr/.virtualenvs/intranet/lib/python2.7/site-packages/punch/file_updater.py", line 25, in update
    new_file_content = self.rep.replace(old_file_content, current_version, new_version)
  File "/home/usr/.virtualenvs/intranet/lib/python2.7/site-packages/punch/replacer.py", line 33, in replace
    new_text = new_text.replace(_search_pattern, _replace_pattern)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 2: ordinal
not in range(128)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.