Git Product home page Git Product logo

csmake's Introduction

csmake

Completely Specified Make (csmake) tool - modular build scripting tool

Overview and Motivation

Most build tools (such as make, ant, maven, etc.) are centered around the idea of delivering one or a handful of results (build artefacts) based around a small set of tools or a single development path. In practice, what we find are a couple of consequences because of this. First, there are many things these build tools "know" how to do intrinsically. In other words, they are built around the 80% of projects that will follow a particular build/development sequence. While these intrinsic pieces are helpful to developers in the tool's sweet spot, often these tend to get in the way of understanding of the build specification, maintainability of the build specification, and the ability to add more automated processes to the tooling that fall soundly outside of the sweet spot. Second, a given build tool only handles one or a couple of parts of the product lifecycle, leaving users to need other tools to automate other pieces of the process (usually shell scripts - if anything at all).

Consider, if make sufficed for all building processes for all time and eternity, why does ant or maven exist? If make covered enough steps of the entire development cycle, why does scons and automake exist? One could simply argue (incorrectly) that this is duplication of effort, the authors didn't want to take the time to learn the tool so they recapitulated it. It's clear to see, given the popularity of ant and maven in some development circles (namely Java, which is their sweet spot), that make either didn't suffice for the needs of these developers, or these tools surpassed make in some way to make their jobs easier. In fact, if we look beyond compiled languages to Python, Ruby, etc. we find that we diverge greatly from the traditional developer workflow tools. I'll pick on Python because the state of affairs here is the bleakest (but rake for Ruby exists, let's not forget...). Distutils, setuptools, pip, virtualenv, setup.py, TOX, unittest, PyPI, Wheels, Eggs, PEPs overriding other PEPs on things like tracking installation of python modules, and on it goes, a never-ending march to reimplement every other conceivable tool, wrapper, concept to fit everything you could ever possibly conceive of doing - until the new next thing is conceived - something these tools don't yet support like - gasp - delivering a man page? Good luck... Python developers have recapitulated the problem of tool specialization in spades. All these various build/developer tools all solve specific problems and like make, ant, etc., and all have been pushed and stretched way beyond their sweet spots (e.g., using pip for production builds - in my option this was never Mr. Bicking's purpose for pip). When it comes to packaging, forget about it - every format has a very specific tool chain and an environment required for building - and cross platform or even distros - well, you're signing up for a lot of hardship and brain damage - not to mention reading, lots and lots of reading.

So, is the alternative a tool that is so generic it does nothing at all? Isn't that the rub? What if the answer was almost yes? Enter, csmake.

csmake provides a developer four basic pieces that every product large and small needs: - A means to specify the build - csmake uses (abuses) the Python (ne Windows) ini format. - A way to say what you are building - csmake provides support for metadata natively - A way to track files through a build process - csmake provides a way to annotate steps (sections) with file tracking and doesn't require that sections participate in the tracking (In other words, file tracking is informative, orthogonal, and optional unless your module(s) use the file tracking information directly) - A way to easily implement custom steps - csmake is extremely modular, so much so that almost everything is a module (there's your almost nothing....without any modules csmake literally does nothing). csmake also provides a developer some modern conveniences: - Similar to maven's idea of workflow, csmake has phases and sequences of phases - Unlike maven's idea of workflow, csmake's phases and order are not dictated by the tool - Similar to make's idea of commands or entry points, csmake has commands (and "multicommands" so you can essentially build an ad-hoc command on the command-line) - Similar to make's (and most build tools) idea of context sensitive execution, csmake uses the "csmakefile" in the current working directory (barring further direction) - Similar to most build tools, csmake can do what most developers would need, or expect if they just typed the command "csmake", provided the csmakefile defines the proper default behaviors - Modules and builds are self-documenting - the documentation is available from the command-line (--help, --help --verbose, --list-phases, --list-commands, --list-type, --list-types) - Modules are object-oriented (full python classes and objects) - It's quite simple to deliver a library of csmake modules - Modules can be defined as aspects that participate in join points and control flow - providing for separation of concerns and builds that can self- heal (Example: I have a flaky git....ok, create an aspect that will catch a git failure and try it again in some cases - no changes to the actual git module required) (Example: I have a problem where I need to temporarily add configuration with a shell script before I execute a section but I can't let it linger for the whole build - ok, decorate the section with a ShellAspect that modifies the configuration at the start of the section and changes it back at the end - again, no changes to the module required)

With this flexibility csmakefiles have been written that: - Recreate diskimage-builder in such a manner that the build process was so flexible, new steps could be added, builds could be halted and reused half way though the process, and steps like pushing builds to archives could be added to a singular build process. - Packaging libraries as debs (and tarballs, and wheels, and soon...rpms) using the same tooling (the csmake installmap and Packager modules) - Also, the packaging is part of the build process. (e.g., csmake build test package - would build, then test, then package the results) - Builds full vm images without the use of a tool like diskimage-builder (and archives the results, etc.) - Generates the proper file staging, renaming, and xml description for HP's SMTA delivery process - Manages expiration and storage (e.g. user access) policy for artefact storage that can be enforced by a build directly or by a "centurion" script that will reset the policy separate from the build - Allow artefacts to be managed and "binned" in the storage based on quality testing (i.e., promotion scripts). - Packages virtualenvs as a tarball (and would also package them as a debian if desired with almost no configuration changes). The next sections go into greater details on each of the points above.

csmake Build Configurations - csmakefiles

A csmakefile is simply a csmake build configuration in a python ini format that calls out the various modules that will be used to perform a build. Each section (except for the [~~phases~~] section) is a reference to a module

For example:

[~~phases~~]
build=Build the csmake example
**default=build

[command@my-command]
0000=do-hello

[Shell@do-hello]
command=set -eux
   echo "Hello"
   echo "World"

This csmakefile has three sections, one is the special "phases" section, and two other sections. The section header contains a label which calls out the module that should be executed, e.g., "command" and "Shell", an '@' symbol, followed by an identifier for the section, e.g., "my-command" and "do-hello". csmake will execute "command" sections from the command-line. If a specific command isn't called out on the command line, csmake will look for a default command section (either [command@] or [command@default]) failing that, it will pick a command section to execute. The modules define what key/value pairs should be used with the section. As you can see from the example above, python ini is fairly free-flowing, allowing multi-line values, providing a free flowing form for things like specifying short shell scripts for example. You can see what a specific module expects for key/value pairs by typing: csmake --list-command=Shell, for example, which would give you the module documentation for Shell.

So, if the above csmakefile was in your current working directory and you type the command:

csmake

You would get several "chunks" of output

% csmake
 ___  ______  ______  ______  ______  ______  ______  ______  ______  ___
  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__
 (______)(______)(______)(______)(______)(______)(______)(______)(______)
     Begin csmake - version 1.5.7
------------------------------------------------------------------
       _   _   _   _   _   _   _   _   _   _   _   _   _   _   _   _
    ,-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)
    `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-'
         BEGINNING PHASE: build
             Build the csmake example
__________________________________________________________________
  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (
------------------------------------------------------------------
+ command@my-command      ---  Begin
------------------------------------------------------------------
__________________________________________________________________
  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (  (
------------------------------------------------------------------
++ Shell@do-hello      ---  Begin
------------------------------------------------------------------
+ echo Hello
Hello
+ echo World
World
------------------------------------------------------------------
 nununununununununununun   Step: Passed   nununununununununununun
------------------------------------------------------------------
++ Shell@do-hello      ---  End
------------------------------------------------------------------
__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)
------------------------------------------------------------------
 nununununununununununun   Step: Passed   nununununununununununun
------------------------------------------------------------------
+ command@my-command      ---  End
------------------------------------------------------------------
__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)
         ENDING PHASE: build
             Build the csmake example
       _   _   _   _   _   _   _   _   _   _   _   _   _   _   _   _
    ,-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)-(_)
    `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-' `-'
   SEQUENCE EXECUTED: build
     Build the csmake example
------------------------------------------------------------------
  .--.      .--.      .--.      .--.      .--.      .--.      .--.      .
:::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::
'      `--'      `--'      `--'      `--'      `--'      `--'      `--'
     csmake: Passed
------------------------------------------------------------------
     End csmake - version 1.5.7
------------------------------------------------------------------
 ___  ______  ______  ______  ______  ______  ______  ______  ______  ___
  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__  __)(__
 (______)(______)(______)(______)(______)(______)(______)(______)(______)

If you use the "quiet" flag, you just get the shell output:

% csmake --quiet
+ echo Hello
Hello
+ echo World
World

Or if you use the "no-chatter" flag, you just get the bare bones "signposts" for each block of execution:

% csmake --no-chatter
     Begin csmake - version 1.5.7
         BEGINNING PHASE: build
             Build the csmake example
+ command@my-command      ---  Begin
++ Shell@do-hello      ---  Begin
+ echo Hello
Hello
+ echo World
World
++ Step Status: Passed
++ Shell@do-hello      ---  End
+ Step Status: Passed
+ command@my-command      ---  End
         ENDING PHASE: build
             Build the csmake example
   SEQUENCE EXECUTED: build
     Build the csmake example
 Step Status: Passed
     End csmake - version 1.5.7

Metadata in csmake

Unless a build is constructed "just for fun", builds are created for the purpose of delivering some kind of "product" which could be an open source developer delivering their library, or a company delivering an installable software solution to their customers. csmake recognizes the problems that arise when there is no consistent way to communicate the metadata of a product, such as the current version, the name or description of the product. csmake defines a "metadata" module and implements internal tracking of this metadata. In fact, the philosophy of using metadata tied to the build is so key in csmake that the file tracking capabilities in csmake are also coupled with the metadata, and of course some builds may actually build several components, so the ability to track metadata for parts of the build is also included.

A metadata section may look like:

[metadata@my-product]
name=my-product
version=1.2.5
description=A product that delivers widgets to web developers
about=The widgets contained in 'my-product' allow developers to do fancy
    cool and neat-o things with their web pages.
 .
 There is no need for this library if you aren't using JavaScript
depends=npm (>= 3), javascript-caffine (> 2)
suggests=javascript-tools (== 2.4.3)
packager=My Product Co, Ltd. <[email protected]>
copyrights=my-product-copyright
keywords=widgets javascript node npm
#classifiers are python trove styled classifiers
# see: https://pypi.python.org/pypi?%3Aaction=list_classifiers
#These will be used to interpret intent of the package based on the packaging
target
classifiers=
   Development Status :: 4 - Beta
   Intended Audience :: Developers
   Topic :: Software Development :: Widget Sets
   Topic :: Internet :: WWW/HTTP :: Dynamic Content
   Programming Language :: JavaScript
   License :: OSI Approved :: MIT License

[copyright@my-product-copyright]
#Copyright license information follows https://www.debian.org/doc/packaging-
manuals/copyright-format/1.0/#license-specification
#Expat is a basic MIT license (there are many versions of the MIT license)
license=Expat
holder=My Product Co, Ltd. <[email protected]>
years=2010,2014-2015
disclaimer=All rights reserved as specified by the license
This is an example of a fairly well developed and comprehensive metadata
section.  Some projects may have several differing attributions which may all
be called out in the "copyrights" key in the metadata, referring to several
different copyrights and licenses associated with the specific attributions.
The minimum required is a project name and a version.  Then, of course, the
metadata can be built up over time as the product becomes more sophisticated
and closer to a release point.
An example of a simple metadata definition might look like:

[metadata@my-product]
name=my-product
version=0.0.0

The version is required to follow the "semantic versioning" standard, with a major.minor.patch level styled version. Other fields may be added to the versioning information using a "versioning" section. The metadata is intended to encapsulate a "best-of-class" definition based on various popular packaging and delivery standards. The most comprehensive resource for defining metadata for your project is found in the module documentation for metadata: csmake --list-type=metadata

File Tracking in csmake

File tracking can be a significant help to anyone building. If it's done well, it's easy to modify your project by adding or deleting files and have the build work without making changes to the build specification. Some tools have some implicit and explicit file tracking. In make, for example, you can define rules where the name of the rule is literally the extension of the file and the output of the step - which may feed to another rule, and so on. In csmake, the file tracking is orthogonal to the rest of the build specification to ensure specifications remain completely specified and the file tracking is easy to use or not use as needed/desired.

To achieve this orthogonality, file-tracking keys may be added to any section that may be completely ignored by the module definition for that section. For example:

[Shell@my-file-generator]
**yields-files=<my-lib (text:placeholder)> touched.txt
command=touch %(RESULTS)s/touched.txt

[CompileCxx@my-cpp-builder]
**maps=<(cpp)> -(1-1)-> <(elf-relocatable)> obj/{~~filename~~}.o
flags=-wall -O3

[LinkStaticLib@my-linker]
**maps=<my-lib (elf-relocatable)> -(*-1)-> <(elf-lib)> libmylib.a
    && <my-other-lib (elf-relocatable)> -(*-1)-> <(elf-lib)> libmyotherlib.a
flags= -L%(SPECIAL_LIB_PATH)s

[command@do-compilations]
**files=
   <my-lib (cpp:library)> *.cpp,
   <my-other-lib (cpp:library)> other/*.cpp
0000=my-file-generator, my-cpp-builder, my-linker

The syntax is a bit cryptic - but essentially what the specification marks out is a way to process two libraries with the same steps. If the CompleCxx and LinkStaticLib modules utilize the file tracking, then this specification would build two libraries based on the *.cpp contents of the current working directory and the "other" directory respectively.

Files in the file tracker have a type and a name, like <my-lib (cpp:library)> *.cpp for example.

The file's type is a 3-axis type system designed to allow for representing different aspects of the file:

< group-id ( file type : intent ) >
- group-id:
   a bucket that any file can be added to.  These buckets
   understand history, and will identify only the final results when only the
   bucket is called out (more on this below)
- file type:
   the literal type of the file - it is encouraged, but not
   required that this is the most specific mime type that describes the file
- intent:
   is a way to annotate what the intended purpose for the file is in
   the build

Each of these axes are useful in different parts of the build, depending on the purpose of a particular section and the whole build specification.

As you can see from the example, in mappings, only partial types need to be used. In the CompileCxx section, we see that we map anything that is a literal file type of "cpp" to an "elf-relocatable" type. The unspecified parts on the right of the mapping are ignored when looking up the files and when parts of the type are unspecified on the left, the resulting file will inherit that part of the type from the left. Again, for the CompileCxx step this means that the .o's will maintain their group-id. So, when the .o's get to the LinkStaticLib step, they will be appropriately linked into the two separate libraries.

As you can also see from the example, there are three different file tracking statements you can add to a step: **files, **yields-files, **maps

- **files:
      a way to tell the build specification that files exist (i.e.,
      are source files) and what type they should be given
- **yields-files:
      a way to tell the build specification that a section
      will produce (or clean, etc) files with the specified type
- **maps:
      defines how a section will map files from one type or
      file pattern to another - mappings can be one of 1-1, *-1, 1-*, or *-*  and,
      as demonstrated, multiple mappings can be defined using the ever popular "and"
      operator (&&)

To leave parts of the type out for the mappings, the proper separators need to be present as things are left out from the left part of the type, for example <my-group> would just be a group, which would only be the last results available in the group (remember, groups maintain history). <(text)> would denote any file designated as a "text" type file. <(:man-page)> would denote (notice the colon to the left of "man-page") a specific purpose for the file (like the purpose of the files we're mapping must be for a manpage, regardless of what format or group the file is in). <(text:man-page)> would denote a text file that has the purpose of being a man-page (maybe not the best choice...) from any group being tracked.

(next parts to add)

Examples
Basic workflow/theory of operation
Hitchhiker's guide to writing csmakefiles
Module Developer's Guide

This material is under the GPL v3 license:

(c) Copyright 2017 Hewlett Packard Enterprise Development LP

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

csmake's People

Contributors

autumn-cpt avatar autumnpat avatar jerpat-hpe avatar

Watchers

 avatar  avatar  avatar

csmake's Issues

v1.6.2 Exit Callbacks failing on chat

` EXCEPTION: Build Exit Callback '<function callbackThunk at 0x7f0151f86f50>' failed on exception
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 1205, in _finishUp
callback()
File "/usr/lib/python2.7/dist-packages/Csmake/CsmakeModule.py", line 70, in callbackThunk
self.log.chatStartOnExitCallback(method)
File "/usr/lib/python2.7/dist-packages/Csmake/Result.py", line 204, in chatStartOnExitCallback
self.reporter.startOnExitCallback(name)
AttributeError: Reporter instance has no attribute 'startOnExitCallback'

Add an option to submetadata to allow filemappings to be transparent in and/or out of the submetadata

entering a submetadata block pushes a clean slate for metadata - which can be extremely annoying when the submetadata's (subproject, really) participates in and needs to refer to the filemappings in its parent project. and needs to pass filemapping back up to the parent project...

initially, the notion was that there needed to be a clean separation between subprojects/submetadata....which is still desireable when, say, four "unrelated" subprojects are built under a single project (which also ensures that the subproject could be built on its own), but in practice, having a way to pull in the parent mappings is wanted many times in my experience.

Undefined environment var in **yields-files doesn't give proper error

The expectation is that useful information would be provided even without debugging in the event that **yields-files references a variable that is not defined.

  EXCEPTION: Attempt to execute step pull-rpm-state failed
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 734, in launchStep
    stepdict )
  File "/usr/lib/python2.7/dist-packages/Csmake/CsmakeModule.py", line 383, in _executeFileMapping
    statement = self.env.doSubstitutions(stepdict['**yields-files'])
  File "/usr/lib/python2.7/dist-packages/Csmake/Environment.py", line 57, in doSubstitutions
    return target % self.env
KeyError: MyVAR

Shell _froms and _tos doesn't work on Centos

The suffix or prefix for bash functions in the environment may differ from environment to environment - we should query the environment to acquire the proper bash function prefix and suffix instead of assume BASH_FUNCTION_ and %%

When an aspect fails but not the step, the step reports a success and a failure for the step

An aspect failed in the execution at the end of the hos-init step.

The step passes, then reports failure.

------------------------------------------------------------------
 nununununununununununun   Step: Passed   nununununununununununun
------------------------------------------------------------------
+++++++ ChrootShell@execute-hos-init      ---  End
------------------------------------------------------------------
__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)__)



subcommand@prepare-hos-deployer-environment: ERROR    : XXXXXX Step 'execute-hos-init' FAILED XXXXXX
` DEBUG    : No joinpoints were defined: failed

Design Change Request: Consider Doing commands and phases differently

instead of:
csmake --command blah phase1 phase2 phase3

It would be really great to be able to say:
csmake blah phase1 phase2 phase3

It would also be really nice to have a default sequence for a command, like:

[command@blah]
description=This is my command
sequence=phase1 -> phase2 -> phase3

It would also be super duper awesome to be able to have labeled sequences stand in for phases:

[~~phases~~]
**sequences=
   deploy: phase1 -> phase2 -> phase3

then the command line would be:
csmake [options] [commands] [sequences] [phases]

phases can literally be anything so they have to go on the end, commands and sequences have to be declared and labeled to be used. We should throw an error if there is an ambiguous command/sequence (same name) and if a declared phase shares a name with a command or sequence.

We should also syntax check the phases (they have to be valid python method names)

The help would need to be restructured to support this...perhaps --show {all (default) | commands | phases} and deprecate --list-commands, etc.

Finally, it would be so awesome to have contextual tab completion

Map with ~ on the right doesn't parse/doesn't error out

**maps= whatever -(1-1)-> ~/stuff/whatever
Will blow up the mapper silently and proceed to map onto the content of the LHS (the identity mapping)

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 1013, in _deriveResultFileFromSource
    return matcher.expand(resultre)
  File "/usr/lib/python2.7/re.py", line 281, in _expand
    template = sre_parse.parse_template(template, pattern)
  File "/usr/lib/python2.7/sre_parse.py", line 762, in parse_template
    s = Tokenizer(source)
  File "/usr/lib/python2.7/sre_parse.py", line 193, in __init__
    self.__next()
  File "/usr/lib/python2.7/sre_parse.py", line 195, in __next
    if self.index >= len(self.string):
TypeError: object of type 'NoneType' has no len()

Is there a way to allow depends sections to have package names with parens?

So, rpm has this funny thing where it has parameterized rpms using dependencies with qualifiers, my current need is: rpmlib(ConcurrentAccess)....it's rpm specific, so I'm torn between saying that the right answer is to use translatePackageName since debian wouldn't have any meaningful translation for these and somehow making it possible in the metadata depends section....

Need a way to dead-end a tracked file

It would be really nice to be able to pull out a file that we need to abandon from the file tracking

E.g.:
**maps=<mybucket> -(1-1)-> _
or:
**sink-files=<mybucket>

We might be able to do something hackish with Shell and command-clean?

_ensureDirectoryExists doesn't work properly with broken soft links

SwiftPullArtefact@get-build-image-from-swift: EXCEPTION: Attempt to execute step 'get-build-image-from-swift' in phase 'pull' failed
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 771, in launchStep
    result = method(stepdict)
  File "/usr/lib/python2.7/dist-packages/CsmakeProviders/CsmakeModules/SwiftPullArtefact.py", line 147, in pull
    self._ensureDirectoryExists(targetFile)
  File "/usr/lib/python2.7/dist-packages/Csmake/CsmakeModule.py", line 298, in _ensureDirectoryExists
    os.makedirs(directory)
  File "/usr/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 17] File exists: './target/archives'
` EXCEPTION: Attempt to execute step get-build-image-from-swift failed
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 809, in launchStep
    raise e
OSError: [Errno 17] File exists: './target/archives'

target/archives is a broken link

Deleting a file in a flow and then doing a map that would have included it fails

In the scenario at hand I generate a file, move it to a new name with a new bucket, then I run a shell command to essentially "dead end" the old bucket (suggested workaround for #40), which works and I get a deleted reference....however, the deleted reference doesn't play nice with future maps that would pull it in.

` EXCEPTION: Attempt to execute step testing-list-raw-disks failed
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 734, in launchStep
    stepdict )
  File "/usr/lib/python2.7/dist-packages/Csmake/CsmakeModule.py", line 381, in _executeFileMapping
    self.mapping = fileManager.parseFileMap(statement)
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 715, in parseFileMap
    result)
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 399, in _dispatchMapper
    result)
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 1081, in mapFilesOneToOne
    toSpec )
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 962, in _deriveResultInstanceSpec
    instance, fromSpec, toSpec )
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 996, in _deriveResultFileFromSource
    sourcere, resultre, instanceAxis = self._determineMatchingLocationFromSource(instance, fromSpec, toSpec)
  File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 989, in _determineMatchingLocationFromSource
    sourcere = instance.getSourceRelLocationRE()
AttributeError: FileRecord instance has no attribute 'getSourceRelLocationRE'

Create an aspect that translates phases

It would be really nice to be able to fit modules into flows where the phases don't quite match up....this should be something that is in the core library and really should be a "keyword" type aspect (i.e., all lower case)

v1.6 Filemap: int has no len() for [~~<int val>~~] substitutions

`
File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 972, in _deriveResultInstanceSpec
newinstanceSpec['location'] = re.sub(r'[%s]' % axis, value, newinstanceSpec['location'])
File "/usr/lib/python2.7/re.py", line 155, in sub
return _compile(pattern, flags).sub(repl, string, count)
File "/usr/lib/python2.7/re.py", line 286, in _subx
template = _compile_repl(template, pattern)
File "/usr/lib/python2.7/re.py", line 271, in _compile_repl
p = sre_parse.parse_template(repl, pattern)
File "/usr/lib/python2.7/sre_parse.py", line 762, in parse_template
s = Tokenizer(source)
File "/usr/lib/python2.7/sre_parse.py", line 193, in init
self.__next()
File "/usr/lib/python2.7/sre_parse.py", line 195, in __next
if self.index >= len(self.string):
TypeError: object of type 'int' has no len()(())

.:~:..:~:..:~:. Step: Failed .:~:..:~:..:~:.

+++ ConvertVirtualImage@create-vhdx --- End

))))))))))))))))))))))
`

Improvement: Find better outputs for file tracking

When there's a problem with file tracking, it's a bit of a nightmare to debug and the file tracking output is inscrutable and barely helpful. It would be good to have a graph (.dot for example) output potential as well as targeted tracking and succinct outputs available as well.

Being able to see the mapping resolution at the beginning of a step's output in --debug would be a huge improvement.

RFE: Add --list-command hook for modules, Documentation feature for ShellToEnvironment

It would be really nice to have a hook that modules can participate in that would print help with --list-command

It would also be nice to be able to add a way inline to document the various ShellToEnvironment entries, like this:
[ShellToEnvironment@my-params]
this=THIS_SHELL:default
This is 'this' documentation
that=THAT_SHELL:another default
This is 'that' documentation

Then, have ShellToEnvironment participate in the hook for --list-command

The hook should be relevant to the commands as entry points

Design Modification: Allow Section Templates

It would be a really nice syntactic sugar to be able to have templated sections where they can be invoked with parameters

Not fully sure what that would look like - there's already a stack, so we'd just need to expand on that....perhaps expand the "env" just for that part - this may work since I've already been considering how to add protected (secret) env elements and this approach may be generic enough to include a stack environment. The trick is to keep the variable resolution fast and obviously correct as well :)

It would be nice if **yields-files environment variables are resolved after the step is completed

**yields-files is technically a cross-cutting action for the file tracking for the step, it would be nice if the environment variables were not processed until the step completes since the mapping doesn't need to be altered until then.

This would benefit the types that yield and environment variable with the results of executing the step that may feed into the file tracking, such as GitDependent

Move to python 3

python 2 is deprecated and quickly becoming unusable for anything of moderate import.

Phase shifts don't work for aspects or Shell variants

When using ChrootShell and PypiFacade together, there was no way to get ChrootShell to accept and execute a phase shift, the phase shift also didn't change the processing for the facade aspect, which could be ok - however, doing any phase or joinpoint shifts on the facade aspect was also definitely not recognized.

[&aspect@thing]
**phases=new->old
[section@thing]
**phases=new->old

csmake new

Will show "Phase shift new -> old"
And then proceed to completely ignore the shift.

1.6.1 - exception when spec not found

EXCEPTION: csmake exited on exception EXCEPTION: AttributeError: NoneType' object has no attribute 'finished

EXCEPTION: Attempt to execute step command@default failed
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 676, in launchStep
raise KeyError("The requested build section '%s' was not found in the build specification" % step)
KeyError: "The requested build section 'command@default' was not found in the build specification"(())` EXCEPTION: csmake exited on exception
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 930, in main
self.realmain()
File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 1121, in realmain
result = self.launchStep(command, phase)
File "/usr/lib/python2.7/dist-packages/Csmake/CliDriver.py", line 902, in launchStep
resultObject.finished()
AttributeError: 'NoneType' object has no attribute 'finished'

create new, separate flag for turning on/off file tracking output

we need a flag separate from dev output that will print out the filetracking states - perhaps keyed to --quiet, --verbose, and --debug so that the level of output can be controlled....it can be helpful for tracking down complex issues to have the output available, but having it tied to --dev-output is impossible to navigate anything else

CliDriver's find_module doesn't have a default for 'path'

def find_module(self, fullname, path)
should be:
def find_module(self, fullname, path=None)

And will yield the cryptic error:
.
.
.
File "/usr/lib/python2.7/pkgutil.py", line 578, in get_data
loader = get_loader(package)
File "/usr/lib/python2.7/pkgutil.py", line 464, in get_loader
return find_loader(fullname)
File "/usr/lib/python2.7/pkgutil.py", line 475, in find_loader
loader = importer.find_module(fullname)
TypeError: find_module() takes exactly 3 arguments (2 given)

File tracking: Problem with failed match

Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/Csmake/FileManager.py", line 1013, in _deriveResultFileFromSource
return matcher.expand(resultre)
File "/usr/lib/python2.7/re.py", line 281, in _expand
template = sre_parse.parse_template(template, pattern)
File "/usr/lib/python2.7/sre_parse.py", line 762, in parse_template
s = Tokenizer(source)
File "/usr/lib/python2.7/sre_parse.py", line 193, in init
self.__next()
File "/usr/lib/python2.7/sre_parse.py", line 195, in __next
if self.index >= len(self.string):
TypeError: object of type 'NoneType' has no len()

An escaping exception in an aspect execution causes execution stack to lose correct pointer

The execution stack got screwed up when an aspect threw an exception.

The specific case was:
command

  • subcommand with an aspect with start/end
  • Shell section with two aspects with start/end (one of these throws an exception in start and possibly end)

It's a fairly complex scenario - should work to repro the failure.
To reproduce this, you'll see sections and aspects start and ends will occur what appears like multiple times...there may be a larger issue with failure handling lurking.

installmap won't accept two user definitions witht the same key

installmap doesn't respect two or more definitions for the same user key

[installmap@my-map]
user_root=TARGET1
user_root=TARGET2
path_root=INSTALL_ROOT
map_test=
    map: <(text:file)> -(1-1)-> {INSTALL_ROOT}/textfiles/[~~file~~]
    user: {TARGET1}
    .
    .
    .

Is likely to fail.

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.