Skip to content

New feature: mbed releases #576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Dec 7, 2017
Merged

Conversation

screamerbg
Copy link
Contributor

@screamerbg screamerbg commented Dec 3, 2017

This feature aims to enhance the workflow for the majority of developers who are looking for stable releases of a program or a library, where these stable revisions usually marked with a source control (Git/Hg) tag.

Workflow

  1. Use mbed import <url> to import a program. Alternatively use mbed new <path> to create a program
  2. Use mbed ls to list the structure of their program.
  3. Use mbed releases [-r] to list available releases for a program or a library <- this PR is aiming at improving this
  4. Use mbed update <release tag> to update to the release

Previously a developer had to fiddle with the relevant source control management (SCM) tool for their program or library. This is somewhat inconvenient as the command set between Git and Mercurial are very different (hg tags vs git show-ref --tags --dereference). Additionally the returned tags might be randomly formatted, which in a repository with large set of tags makes it hard to spot which are release/stable tags. mbed releases filters the displayed release tags based on commonly tag format (see https://git-scm.com/book/en/v2/Git-Basics-Tagging)

How this works

Listing the releases for the current program or library is done via mbed releases, e.g.

$ mbed import mbed-os-example-wifi
[SNIP]

$ mbed releases
mbed-os-example-wifi (#f9f04508a860, tags:mbed-os-5.6.5)
  * mbed-os-5.2.0 
  * mbed-os-5.2.1 
  * mbed-os-5.2.3 
  * mbed-os-5.3.0 
  * mbed-os-5.3.1 
  * mbed-os-5.3.2 
  * mbed-os-5.3.3 
  * mbed-os-5.3.4 
  * mbed-os-5.3.5 
  * mbed-os-5.3.6 
  * mbed-os-5.4 
  * mbed-os-5.4.1 
  * mbed-os-5.4.2 
  * mbed-os-5.4.3 
  * mbed-os-5.4.5 
  * mbed-os-5.5.1 
  * mbed-os-5.5.3 
  * mbed-os-5.5.5 
  * mbed-os-5.5.6 
  * mbed-os-5.5.7 
  * mbed-os-5.6.0 
  * mbed-os-5.6.1 
  * mbed-os-5.6.4 
  * mbed-os-5.6.5  <- current

Command switch -a is used to list release-hash pairs, e.g.

$ mbed releases -a
mbed-os-example-wifi (https://github.com/ARMmbed/mbed-os-example-wifi#f9f04508a860)
  * mbed-os-5.2.0 #23dfd8dbd33fdf17ed073ce29457ac722e200b08
  * mbed-os-5.2.1 #bc18a5c587e198d8e2b04f31c3314b25923ea1ff
  * mbed-os-5.2.3 #286f573a7a36a63c3c772c4fd28f84c545b54996
  * mbed-os-5.3.0 #57997dc40b71e91ab3214fdcb28c8cf2f0ca3d0e
  * mbed-os-5.3.1 #9cc04848da087cec959ae43caa2e3a3e390910f5
  * mbed-os-5.3.2 #8cb627404c04d3476989a2a0bdaf932e54f64a34
  * mbed-os-5.3.3 #27bfaf4a1f1d612c9fa5c04b1931559333576d78
  * mbed-os-5.3.4 #c8ea0d5489140fb0d13637b3b6c6715e4d0a3781
  * mbed-os-5.3.5 #6b4da1f52f3310c26b7fa71624cfc89134cbeb0c
  * mbed-os-5.3.6 #d3e0a72df157ab785f9f90130200bff2f32747b1
  * mbed-os-5.4 #3f6ee363545eb8a214056b1c5bf824223d5c7352
  * mbed-os-5.4.1 #a63841142aa9ed70f9c51b35325acbb58c24957d
  * mbed-os-5.4.2 #0b0f859c563bba23bef9591ddcb0711834026157
  * mbed-os-5.4.3 #83a1e84c8fe8a2ae333529b7971524a9ea5e8f32
  * mbed-os-5.4.5 #1c2d7cc3c4c4dd5969d2d73c3116c85622302fb3
  * mbed-os-5.5.1 #82638173e0feaf551df125fda0e19f85a8e608b1
  * mbed-os-5.5.3 #3fa3697d3184902c2eb348a59a2e7213c567bd17
  * mbed-os-5.5.5 #51649fb108cb7bbb43ba1b70acb005b3bbbeeba1
  * mbed-os-5.5.6 #0a3ffdeb12992b401b6b5ad8d1b09517cabef1be
  * mbed-os-5.5.7 #8f9c590da6a7e7d20dd4f98aea05539955dd9794
  * mbed-os-5.6.0 #1097ea0e420efc79d19ab9530292eea1d8ba7166
  * mbed-os-5.6.1 #908027f05043aed5aab4d9d4b18132eec1f32452
  * mbed-os-5.6.4 #8d539eef1f75b0a11f640c67da6d091d374c5792
  * mbed-os-5.6.5 #f9f04508a8605c258dc61f68a493461b29966588 <- current

While by default this command works for the current program or library, the -r switch enables recursive listing in a tree format similar to mbed ls, e.g.

$ mbed releases -r
mbed-os-example-wifi (#f9f04508a860, tags:mbed-os-5.6.5)
| * mbed-os-5.2.0 
| * mbed-os-5.2.1 
| * mbed-os-5.2.3 
| * mbed-os-5.3.0 
| * mbed-os-5.3.1 
| * mbed-os-5.3.2 
| * mbed-os-5.3.3 
| * mbed-os-5.3.4 
| * mbed-os-5.3.5 
| * mbed-os-5.3.6 
| * mbed-os-5.4 
| * mbed-os-5.4.1 
| * mbed-os-5.4.2 
| * mbed-os-5.4.3 
| * mbed-os-5.4.5 
| * mbed-os-5.5.1 
| * mbed-os-5.5.3 
| * mbed-os-5.5.5 
| * mbed-os-5.5.6 
| * mbed-os-5.5.7 
| * mbed-os-5.6.0 
| * mbed-os-5.6.1 
| * mbed-os-5.6.4 
| * mbed-os-5.6.5  <- current
|- esp8266-driver (#b0d79dad507d)
|    * v1.0 
|    * v1.1 
|    * v1.2 
|    * v1.3 
|    * v1.4 
|- mbed-os (#182bbd51bc8d, tags:latest, mbed-os-5.6.5)
|    * mbed-os-5.1.0 
|    * mbed-os-5.1.1 
|    * mbed-os-5.1.2 
|    * mbed-os-5.1.3 
|    * mbed-os-5.1.4 
|    * mbed-os-5.1.5 
|    * mbed-os-5.2.0 
|    * mbed-os-5.2.1 
|    * mbed-os-5.2.2 
|    * mbed-os-5.2.3 
|    * mbed-os-5.3.0 
|    * mbed-os-5.3.1 
|    * mbed-os-5.3.2 
|    * mbed-os-5.3.3 
|    * mbed-os-5.3.4 
|    * mbed-os-5.3.5 
|    * mbed-os-5.3.6 
|    * mbed-os-5.4.0 
|    * mbed-os-5.4.1 
|    * mbed-os-5.4.2 
|    * mbed-os-5.4.3 
|    * mbed-os-5.4.4 
|    * mbed-os-5.4.5 
|    * mbed-os-5.4.6 
|    * mbed-os-5.4.7 
|    * mbed-os-5.5.0 
|    * mbed-os-5.5.1 
|    * mbed-os-5.5.2 
|    * mbed-os-5.5.3 
|    * mbed-os-5.5.4 
|    * mbed-os-5.5.5 
|    * mbed-os-5.5.6 
|    * mbed-os-5.5.7 
|    * mbed-os-5.6.0 
|    * mbed-os-5.6.1 
|    * mbed-os-5.6.2 
|    * mbed-os-5.6.3 
|    * mbed-os-5.6.4 
|    * mbed-os-5.6.5  <- current
`- wifi-x-nucleo-idw01m1 (#5871f7011d7f)
     No release tags detected

Also, one can list unstable release tags, usually release candidates, alphas, betas, using the -u switch. This relaxes the release/tag name matcher to include a wider set of tags (see https://git-scm.com/book/en/v2/Git-Basics-Tagging again)

$ mbed releases -u
mbed-client (#31e5ce203cc0, tags:v3.0.0)
  * mbed-os-5.0-rc1 
  * mbed-os-5.0-rc2 
  * r0.5-rc4 
  ...
  * v2.2.0 
  * v2.2.1 
  * v3.0.0  <- current

Lastly, the implementation enhances mbed ls as well and makes it release/tag "aware". Here's an example:

$ mbed ls
mbed-os-example-client (#46555484a88d, tags:mbed-os-5.5.4)
|- easy-connect (#211cdf2bfa33)
|  |- atmel-rf-driver (#0ae76ce17ae5)
|  |- esp8266-driver (#ebc1fbd0b53a)
|  |  `- ESP8266/ATParser (#77734ee44a63)
|  |- mcr20a-rf-driver (#d5905fefa54c)
|  `- stm-spirit1-rf-driver (#09e4b9664de1)
|- mbed-client (#31e5ce203cc0, tags:v3.0.0)
|  |- mbed-client-c (#ecfa619e42b2, tags:v6.0.0)
|  |- mbed-client-classic (#4e66929607c3)
|  `- mbed-client-mbed-tls (#7e1b6d815038, tags:mbedCloudClient-R1.1, mbedCloudClient-R1.1-RC1)
|- mbed-os (#4c256f045961, tags:mbed-os-5.5.4, mbed_lib_rev148)
`- pal (#60ce64d5ec35)

Documentation
Documentation is included with this PR. Firstly mbed releases is briefly mentioned in the Importing/Creating section. Then it's more reviewed in detail in the "Update" section as a prerequisite for an update workflow (as per the description above).

@AnotherButler please review

Tests
Releases are listed recursively (using mbed releases -r) for both Git, Mercurial and Mbed 2/Classic repositories as part of the circle CI tests.

The feature was inspired by a conversation with @adbridge regarding releases process, release candidates, release tags, release XYZ, and end-developer workflows :)

CC @sg- @adbridge @MarceloSalazar

…am or library.

This enables listing of tags matched against common release naming patterns, e.g. v1.2, r1.3.5, mbed-os-5.1.2, etc
The command supports the following switches
 -a|-all - Show all, including release candidates, alpha, betas
 -r|--recursive - Show releases for all libraries and sub-libraries as well

Also `mbed ls` uses some of the routines from `mbed releases` and now shows associated tags/releases
Copy edit for consistent phrasing and active voice.
Copy link
Contributor

@bridadan bridadan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really slick! This is going to be such a great help to our users, I know people have had issues with this in the past, great to see it being handled so well here!

I've added a few comments to the docs/logs to help clarify the finer points of the new features.

Awesome work!

mbed/mbed.py Outdated
repo = Repo.fromrepo()
tags = repo.scm.gettags()
revtags = repo.scm.gettags(repo.rev) if repo.rev else [] # associated tags with current commit
revstr = ('#'+repo.rev[:12]+(', tags:'+', '.join(revtags[0:2]) if len(revtags) else '')) if repo.rev else ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a formatting nitpick, but I think it helps users more quickly scan for matching revisions.

Currently its setup to print like the following:

`- mbed-os (#182bbd51bc8d, tags:latest, mbed-os-5.6.5)

What do you think of the following changes?

  • Add a space between tags: and the list of tags
  • Wrap the list of tags with [] to help differentiate the comma-separated list from the commit that comes before it

So as an example:

`- mbed-os (#182bbd51bc8d, tags: [latest, mbed-os-5.6.5])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the space after tags. The list wrapped in [] seems a lot like taken from the json/javascript world though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the spaces. We don't have to use [], I was mostly thinking about how we can we show that latest and mbed-os-5.6.5 are part of the tags instead of another item in the existing list (the one containing #182bbd51bc8d and tags: ...). My eyes in particular have trouble separating all the different bits in this line since it contains a lot of (very useful) information.

If you think () would be a better container than [], that's totally fine with me! But if you don't think this is necessary, then no biggie!

README.md Outdated
@@ -741,6 +756,42 @@ The update command fails if there are changes in your program or library that `m

### Updating to an upstream version

Before updating a program or a library, it's good to know the names of the stable releases, usually marked with a tag using a common format, such as `1.2`, `v1.0.1`, `r5.6`, `mbed-os-5.6` and so on.
Copy link
Contributor

@bridadan bridadan Dec 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is really helpful for determining what will be considered "stable" release. It looks like you're using a regular expression to determine this.

Would it also be possible to add to the docs the specific rules you're checking for? For instance, "Starts with v, r mbed-os-, etc" and "does not end in rcxxxx". Just a list detailing the specific conditions would be super helpful in addition to the example you gave above.

@adbridge
Copy link
Contributor

adbridge commented Dec 4, 2017

@screamerbg Great work, took my original ideas, improved them and rolled out a really, really useful command addition!

Copy link
Contributor

@adbridge adbridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll let Jimmy and Brian do the in depth Python reviewing. Rest looks good!

Copy link
Contributor

@theotherjimmy theotherjimmy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code questions follow.

mbed/mbed.py Outdated
for ref in refs:
m = re.match(r'^(.+)\s+(.+)$', ref)
if m and (not rev or m.group(1).startswith(rev)):
if re.match(r'refs\/tags\/', m.group(2)): # only tags
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have a series of regexps? Could this all be folded into one regexp?

mbed/mbed.py Outdated
if re.match(r'refs\/tags\/', m.group(2)): # only tags
t = re.sub(r'refs\/tags\/', '', m.group(2))
if re.match(r'^(.+)\^\{\}$', t): # detect tag "symlink"
t = re.sub(r'\^\{\}$', '', t) # remove "symlink" chars, e.g. some-tag^{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain what a "tag symlink" is? I don't see any in my git show-ref output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try git show-ref --tags --dereference. A quote from stackoverflow:
In git, a "normal" (annotated, not lightweight) tag is an object unto itself, containing metadata and the SHA1 of the object it tags. There's a pretty picture in the section of the git community book on the git object model (scroll to the bottom). So, when you use show-ref on a normal tag, it will normally give you information about the tag object. With the -d/--dereference option, it will dereference the tag into the object the tag refers to, and provide information about it instead. And a note on lightweight vs. annotated tags, in case you aren't aware of that: a lightweight tag is created by using git tag (i.e. without any of the metadata-providing options like -a, -s, or -u). It's not a tag object at all, just a ref pointing straight to the object you've tagged. If you provide one of those options, you're attaching metadata to the tag, so git creates a tag object to hold that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@screamerbg That tells me that some tags are references and some are tag objects. How do "symlinks" get involved here?

Copy link
Contributor

@theotherjimmy theotherjimmy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is entirely about spaces around + operators.

mbed/mbed.py Outdated
@@ -2123,21 +2163,63 @@ def sync(recursive=True, keep_refs=False, top=True):
"View the dependency tree of the current program or library."))
def list_(detailed=False, prefix='', p_path=None, ignore=False):
repo = Repo.fromrepo()
revtags = repo.scm.gettags(repo.rev) if repo.rev else []
revstr = ('#'+repo.rev[:12]+(', tags: '+', '.join(revtags[0:2]) if len(revtags) else '')) if repo.rev else ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add spaces around the + operators in this line?

revstr = ('#' + repo.rev[:12] + (', tags: ' + ', '.join(revtags[0:2]) if len(revtags) else '')) if repo.rev else 

mbed/mbed.py Outdated

print "%s (%s)" % (prefix + (relpath(p_path, repo.path) if p_path else repo.name), ((repo.url+('#'+str(repo.rev)[:12] if repo.rev else '') if detailed else str(repo.rev)[:12]) or 'no revision'))
print "%s (%s)" % (prefix + (relpath(p_path, repo.path) if p_path else repo.name), ((repo.url+('#'+str(repo.rev)[:12] if repo.rev else '') if detailed else revstr) or 'no revision'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a single space around the + operators in this line too?

print "%s (%s)" % (prefix + (relpath(p_path, repo.path) if p_path else repo.name), ((repo.url + ('#' + str(repo.rev)[:12] if repo.rev else '') if detailed else revstr) or 'no revision')) 

mbed/mbed.py Outdated
repo = Repo.fromrepo()
tags = repo.scm.gettags()
revtags = repo.scm.gettags(repo.rev) if repo.rev else [] # associated tags with current commit
revstr = ('#'+repo.rev[:12]+(', tags: '+', '.join(revtags[0:2]) if len(revtags) else '')) if repo.rev else ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a space around the + operators here too?

revstr = ('#' + repo.rev[:12] + (', tags: ' + ', '.join(revtags[0:2]) if len(revtags) else '')) if repo.rev else ''

mbed/mbed.py Outdated
rels = []
for tag in tags:
if re.match(regex_rels, tag[1]):
rels.append(tag[1] + " %s%s" % ('#'+tag[0] if detailed else "", " <- current" if tag[1] in revtags else ""))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another + operator in need of some spaces.

rels.append(tag[1] + " %s%s" % ('#' + tag[0] if detailed else "", " <- current" if tag[1] in revtags else ""))

mbed/mbed.py Outdated
rels.append(tag[1] + " %s%s" % ('#'+tag[0] if detailed else "", " <- current" if tag[1] in revtags else ""))

# Print header
print "%s (%s)" % (prefix + (relpath(p_path, repo.path) if p_path else repo.name), ((repo.url+('#'+str(repo.rev)[:12] if repo.rev else '') if detailed else revstr) or 'no revision'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spaces around the + op here too.

print "%s (%s)" % (prefix + (relpath(p_path, repo.path) if p_path else repo.name), ((repo.url + ('#'+str(repo.rev)[:12] if repo.rev else '') if detailed else revstr) or 'no revision'))

mbed/mbed.py Outdated
rprefix += '| ' if recursive and len(repo.libs) > 1 else ' '
if len(rels):
for rel in rels:
print rprefix+'* '+rel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These + ops could use a space too.

print rprefix + '* ' + rel

mbed/mbed.py Outdated
for rel in rels:
print rprefix+'* '+rel
else:
print rprefix+'No release tags detected'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This + operator could use some separating spaces as well.

 print rprefix + 'No release tags detected'

Copy link
Contributor

@bridadan bridadan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

@screamerbg
Copy link
Contributor Author

Thanks everyone. Let's get this in.

@screamerbg screamerbg merged commit 52f3cbb into ARMmbed:master Dec 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants