Build helpers
The following helper functions can help you build your package correctly. Attach() is specifically for debugging, while the other helper functions support package builds.
Note
plan.ps1). However, in most cases, standard PowerShell cmdlets provide the same functionality. For example, use Resolve-Path instead of abspath, or Get-Command instead of exists.attach()plan.shonly. Attaches your script to an interactive debugging session, which lets you check variable state, call arbitrary functions, and turn on higher logging levels with theset -xoption.To use
attach, addattachto any callback or part of yourplan.shfile, and the debugging session starts whenhab-plan-buildreaches that part of the file.Note
Use the native PowerShell cmdletSet-PSBreakpointfor debuggingplan.ps1functions. You can set its-Commandparameter to any build phase function.download_file()plan.shonly. Downloads a file from a source URL to a local file, and uses an optional shasum to determine if an existing file can be used.download_file <source_url> <local_file> [<shasum>]If an existing file is present and the third argument is set with a shasum digest, the file is checked to confirm it’s valid. If so, the function ends early and returns 0. Otherwise, the shasums don’t match, so the file on disk is removed and a normal download proceeds as though no previous file existed. This is designed to restart an interrupted download.
Any valid
wgetURL will work.Downloads every time, even if the file exists locally:
download_file http://example.com/file.tar.gz file.tar.gzDownloads if no local file is found:
download_file http://example.com/file.tar.gz file.tar.gz expected_shasumFile matches checksum: download is skipped, local file is used:
download_file http://example.com/file.tar.gz file.tar.gz expected_shasumFile doesn’t match checksum: local file removed, download attempted:
download_file http://example.com/file.tar.gz file.tar.gz mismatching_shasumWill return 0 if a file was downloaded or if a valid cached file was found.
pkg_path_for()/Get-HabPackagePath- Returns the path for a build-time or runtime package dependency on stdout from the dependencies listed in
pkg_depsorpkg_build_deps. This is useful if you need to install or reference specific dependencies from within a callback, such asdo_build()ordo_install().The following example uses this function to retrieve the path to the Perl binary in the
core/perlpackage:_perl_path="$(pkg_path_for core/perl)/bin/perl" fix_interpreter()plan.shonly. Edits the#!shebang of the target file in place. This is useful for changing hard-coded paths in your source files to the equivalent path in a Chef Habitat package. You must include the required package that provides the expected shebang path inpkg_deps. This function performs a greedy match against the specified interpreter in target files.To use this function in your plan, you must specify the following arguments:
- The target file or files
- The name of the package that contains the interpreter
- The relative directory and binary path to the interpreter
For example, to replace all the files in
node_modules/.binthat have#!/usr/bin/envwith the coreutils path tobin/env(/hab/pkgs/core/coreutils/8.24/20160219013458/bin/env), you must quote the wildcard target as shown below.fix_interpreter "node_modules/.bin/*" core/coreutils bin/envFor a single target, reference the file directly:
fix_interpreter node_modules/.bin/concurrent core/coreutils bin/envpkg_interpreter_for()plan.shonly. Returns the path for the given package and interpreter by reading it from the INTERPRETERS metadata in the package. The directory of the interpreter needs to be specified, as an interpreter binary might live inbin,sbin, orlibexec, depending on the software.The following shows how to call
pkg_interpreter_forwith the package and interpreter arguments specified.pkg_interpreter_for core/coreutils bin/envThis function returns 0 if the specified package and interpreter are found, and 1 if the package can’t be found or the interpreter isn’t specified for that package.
pkg_version()- An optional way to determine the value for
$pkg_version. The function must print the computed version string to standard output and is called when the plan author invokes theupdate_pkg_version()helper in aplan.shorSet-PkgVersionin aplan.ps1. update_pkg_version()/Set-PkgVersion- Updates the value for
$pkg_versionby calling a plan author-providedpkg_version()function. You must explicitly call this function in or after thedo_before()/Invoke-Beforebuild phase, but before thedo_prepare()/Invoke-Preparebuild phase. The$pkg_versionvariable is updated, and any other relevant variables are recomputed. The following examples show how to use these functions to set a dynamic version number.This plan concatenates a static file in the source root of the project to determine the version in the
beforephase:pkg_version() { cat "$SRC_PATH/version.txt" } do_before() { do_default_before update_pkg_version }function pkg_version { Get-Content "$SRC_PATH/version.txt" } Invoke-Before { Invoke-DefaultBefore Set-PkgVersion }The
pkg_versionfunction in this plan dynamically creates a version with a date stamp and outputs the final version string to standard output. As the downloaded file is required before running the version logic, this helper function is called in thedownloadbuild phase:pkg_version() { local build_date # Extract the build date of the certificates file build_date=$(cat $HAB_CACHE_SRC_PATH/$pkg_filename \ | grep 'Certificate data from Mozilla' \ | sed 's/^## Certificate data from Mozilla as of: //') date --date="$build_date" "+%Y.%m.%d" } do_download() { do_default_download update_pkg_version }function pkg_version { # Extract the build date of the certificates file $matchStr = "## Certificate data from Mozilla as of: " foreach($line in (Get-Content "$HAB_CACHE_SRC_PATH/$pkg_filename")) { if($line.StartsWith($matchStr)) { $build_date = $line.Substring($matchStr.Length) } } [DateTime]::Parse($build_date).ToString("yyyy.mm.dd") } function Invoke-Download { Invoke-DefaultDownload Set-PkgVersion } abspath()plan.shonly. Returns the absolute path for a path, which can be absolute or relative.exists()plan.shonly. Checks whether a command exists. Returns 0 if it does, and 1 if it doesn’t.build_line()/Write-BuildLine- Prints a line of build output. Takes a string as its only argument.
build_line "Checksum verified - ${pkg_shasum}" warn()/Write-Warning- Prints a warning line on stderr. Takes a string as its only argument.
warn "Checksum failed" debug()/Write-Debug- Prints a line only if the
$DEBUGenvironment variable is set to 1. Thedebugfunction takes a string as its only argument.DEBUG=1 debug "Only if things are set" exit_with()plan.shonly. Exits the program with an error message and status code.exit_with "Something bad happened" 55trim()plan.shonly. Trims leading and trailing whitespace from a Bash variable.record()plan.shonly. Takes a session name and command to run as arguments, then appends a timestamp to the log file. This is an alternative to piping a build throughtee.# Usage: record <SESSION> [CMD [ARG ...]] record mysoftware build /src/mysoftware