diff --git a/UsingSampleStack.md b/UsingSampleStack.md new file mode 100644 index 0000000..2ef109f --- /dev/null +++ b/UsingSampleStack.md @@ -0,0 +1,62 @@ +# Using Sample Stack + +## Using Sample Application stack + +1. Clone or copy the "sample-stack" [git repository](https://github.com/application-stacks/sample-stack) +1. Change directory to the `sample-stack` directory +1. Delete the `starter` directory (which contains the starter stack) +1. Create a new stack directory, within the base directory of the Git repository, to contain the stack to be published. For example: + ``` + mkdir ./my-nodejs + ``` +1. Copy or create your stack in this new directory. Look at [Developing Stacks](https://appsody.dev/docs/stacks/develop) for information on how to create a stack. +1. Package and test your stack. There are 2 ways that you can package and test your stack. These are: + 1. Using the Appsody CLI `stack` commands, see [Packaging stacks](https://appsody.dev/docs/stacks/package) + 1. Using the CI scripts provided within the sample-stack repo, see [Packaging a stack using CI scripts](#Packaging-a-stack-using-CI-scripts) + > If using Travis CI within your git repository, it may be preferable to use the CI scripts as they are used when you push your stack to your git repository. +1. Once you have developed, packaged and tested your stack you then push your repository to your GitHub organization. i.e. `https://github.com/myorg/my-nodejs` + +## Packaging a stack using CI scripts + +1. Use environment variables to override default settings that are used by the build script, for example the namespace to use for the Docker images, and the URL to use to reference the template archive files. The main variables to override are: + + - `IMAGE_REGISTRY_ORG` this is the namespace to create the Docker images with. + - `RELEASE_URL` this is the base URL to your web hosting service, and is used to reference the template archive files from within the repository index file. + + You can set these environment variables by exporting them. For example: + + ``` + export IMAGE_REGISTRY_ORG=myproject + export RELEASE_URL=https://github.com/myorg/my-nodejs/releases/latest/download + ``` +1. Run the build script from the base directory of the git repository. For example: + ``` + ./ci/build.sh + ``` + This command creates the following artefacts in the `./ci/assets` directory: + * stack index file (containing remote URLs) + * template archive files + * stack source file + + and in the local docker registry: + * stack container images + +## Configure Git repository to use Travis to build stack + +To configure your git repository to use Travis CI follow the "Get started with Travis using Github" [instructions](https://docs.travis-ci.com/user/tutorial/#to-get-started-with-travis-ci-using-github) + +The "sample-stack" [git repository](https://github.com/application-stacks/sample-stack) contains the files that provide support for building and releasing of the stack. These file are: + +* ./ci/* : the CI scripts that will perform the build and the release of the stack +* ./travis.yml : the travis configuration file + +Similar to when running the CI scripts locally, there are environment variables that need to be setup within your Travis environment. Use the "Defining Variables in Repository Setting" [Travis documentation](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings) to define environment variables. + +The environment variables you will need to override are: + + - `IMAGE_REGISTRY_ORG` this is the namespace to create the Docker images with. + - `RELEASE_URL` this is the base URL to your web hosting service, and is used to reference the template archive files from within the repository index file. + - `CODEWIND_INDEX` this specifies whether to build the indexfile for use with Codewind. Default=false. + - `GITHUB_TOKEN` this is a user access token to allow access to your Github org. + - `IMAGE_REGISTRY_USERNAME` this is the username that will be used to logon to your docker registry when publishing the docker images. + - `IMAGE_REGISTRY_PASSWORD` this is the password that will be used to logon to your docker registry when publishing the docker images. diff --git a/ci/ci_wait.sh b/ci/ci_wait.sh new file mode 100755 index 0000000..c8f89b5 --- /dev/null +++ b/ci/ci_wait.sh @@ -0,0 +1,350 @@ +#!/bin/bash + +# The MIT License (MIT) + +# Copyright (c) 2015 +# m3t (96bd6c8bb869fe632b3650fb7156c797ef8c2a055d31dde634565f3edda485b) + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Available from https://github.com/m3t/travis_wait +# Please report bugs at https://github.com/m3t/travis_wait/issues + +# Coding (Style) Guidelines: +# https://www.chromium.org/chromium-os/shell-style-guidelines +# http://mywiki.wooledge.org/BashGuide/Practices +# http://wiki.bash-hackers.org/scripting/style + + +# bash available? +if [ -z "$BASH_VERSINFO" ]; then + echo "Please make sure you're using bash!" + exit 1 +fi + + +# INITIALIZE CONSTANTS AND GLOBALS +# Only lower case, esp. for export! +# That ensures that system vars stay untouched in any case +readonly prog_name=$(basename "$0") + + +is_writeable() { + local var="$1" + + is_writeable_empty "${var}" 0 +} + +is_writeable_empty() { + local var="$1" + local empty="$2" + [[ -z "${empty}" ]] && empty=1 + + # http://mywiki.wooledge.org/BashGuide/TestsAndConditionals + # "touch" creates file, if it doesn't exist, + # so further tests won't fail at the beginning + if { touch -a "${var}" >/dev/null 2>&1; }; then + if [[ ! -s "${var}" ]]; then + if [[ ! -w "${var}" ]]; then + #show_warning "${var} is not writeable" + return 1 + fi + else + #show_warning "${var} is not empty" + [[ "${empty}" -eq 1 ]] && return 1 + fi + else + #show_warning "Destination for ${var} is not accessible at all" + return 1 + fi + + return 0 +} + +is_number() { + local int="$1" + # http://mywiki.wooledge.org/BashFAQ/054 + [[ "$int" != *[!0-9]* ]] +} + +is_empty() { + local var="$1" + + [[ -z "$var" ]] +} + +show_error() { + printf "\n%s\n" "${prog_name}: error: $*" >&2 + exit 1 +} + +show_warning() { + printf "\n%s\n" "${prog_name}: $*" >&2 +} + +show_output() { + printf "%s\n" "${prog_name}: $*" +} + +show_help() { + # http://wiki.bash-hackers.org/syntax/redirection#here_documents + cat <<- EOF + + Usage: ${prog_name} [options] + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + Arguments: + Slowpoke command + + + Options: + -i, --interval Refresh interval in sec. + Default: 30 + + -l, --limit Limit execution time in sec. + Default: 0 (Off) + + -x, --exit-code Force the exit code + Default: -1 (Off) + + -a, --append PRN append output to existing logfile + Off: 0 (Default) + On: 1 + + -o, --output Where 's output will be saved + Default: \$RANDOM-output.log + + -h This help screen + + + Copyright (C) 2015 m3t + The MIT License (MIT) + +EOF + + exit 0 +} + +cleanup() { + kill -0 ${pid_slowpoke} >/dev/null 2>&1 && kill ${pid_slowpoke} >/dev/null 2>&1 +} + +running() { + if ps -p $1 > /dev/null; then + return 0 + else + return 1 + fi +} + +main() { + + # INITIALIZE LOCAL VARIABLES + # Variables to be evaluated as shell arithmetic should be initialized + # to a default or validated beforehand. + # CAUTION: Arguments' (not options) default values will be overwritten here anyway + # So they are set in VALIDATE INPUT + local i=0 + local msg="" + local time_passed=0 + local pid_slowpoke=0 + local exit_slowpoke=0 + # Options: + local interval=30 + local time_limit=0 + local exit_force=-1 + local append=0 + # Arguments: + local cmd_slowpoke="" + local file_log="" + + + # SIGNAL HANDLING + # http://mywiki.wooledge.org/SignalTrap + # http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT + trap 'cleanup; trap - INT; kill -INT $$' INT QUIT # CTRL+C OR CTRL+\ + trap 'cleanup; exit 1' TERM # kill's default signal + + + # COMMAND-LINE ARGUMENTS AND OPTIONS + # http://mywiki.wooledge.org/BashFAQ/035 + msg="requires a non-empty option argument." + while :; do + case "$1" in + -h|-\?|--help) + show_help + exit + ;; + -l|--limit) + if [ -n "$2" ]; then + time_limit="$2" + shift 2 + continue + else + show_error "--limit ${msg}" + fi + ;; + --limit=?*) + time_limit="${1#*=}" + ;; + --limit=) + show_error "--limit ${msg}" + ;; + -i|--interval) + if [ -n "$2" ]; then + interval="$2" + shift 2 + continue + else + show_error "--interval ${msg}" + fi + ;; + --interval=?*) + interval="${1#*=}" + ;; + --interval=) + show_error "--interval ${msg}" + ;; + -x|--exit-code) + if [ -n "$2" ]; then + exit_force="$2" + shift 2 + continue + else + show_error "--exit-code ${msg}" + fi + ;; + --exit-code=?*) + exit_force="${1#*=}" + ;; + --exit-code=) + show_error "--exit-code ${msg}" + ;; + -a|--append) + if [ -n "$2" ]; then + append="$2" + shift 2 + continue + else + show_error "--append ${msg}" + fi + ;; + --append=?*) + append="${1#*=}" + ;; + --append=) + show_error "--append ${msg}" + ;; + -o|--output) + if [ -n "$2" ]; then + file_log="$2" + shift 2 + continue + else + show_error "--output ${msg}" + fi + ;; + --output=?*) + file_log="${1#*=}" + ;; + --output=) + show_error "--output ${msg}" + ;; + --) # End of all options. + shift + break + ;; + -?*) + show_warning "Unknown option (ignored): $1" + ;; + *) # Default case: If no more options then break out of the loop. + break + esac + + shift + done + # Arguments following the options + # will remain in the "$@" positional parameters. + cmd_slowpoke="$@" + + # VALIDATE INPUT + is_number "${interval}" || show_error "Interval is not a valid number" + is_number "${time_limit}" || show_error "Limit is not a valid number" + is_empty "$@" && show_error "Command to execute is not given. See --help." + is_empty "${file_log}" && file_log="$RANDOM-output.log" # http://mywiki.wooledge.org/BashFAQ/062 + + show_output "Watching command: $@" + show_output "Sending output to ${file_log}" + show_output "Will check for completion every ${interval} seconds, with maximum wait of ${time_limit} seconds." + + # START CMD + # http://mywiki.wooledge.org/ProcessManagement + if [[ "${append}" -ne 1 ]]; then + is_writeable_empty "${file_log}" || show_error "${file_log} is not writeable or not empty." + $@ > "${file_log}" 2>&1 & pid_slowpoke=$! + else + is_writeable "${file_log}" || show_error "${file_log} is not writeable." + $@ >> "${file_log}" 2>&1 & pid_slowpoke=$! + fi + + # WAIT + # Terminates when $cmd_slowpoke is finished + # OR + # $time_limit has reached + i=0 + while running ${pid_slowpoke}; do + : $(( time_passed = i * interval )) + + # Output last line from $file_log + show_output $(tail -1 "${file_log}") + + # $time_limit + if [[ "${time_limit}" -ne 0 ]] && [[ "${time_passed}" -ge "${time_limit}" ]]; then + show_warning "Time limit exceeded. Cleaning up." + cleanup + printf "\n%s\n" "${prog_name}: Time limit exceeded." >> ${file_log} + break + fi + + sleep ${interval} + + : $(( i += 1 )) + done + + + # FINISHED + # Shall I fake the exit code? + if ! is_number "${exit_force}"; then + # Get exit code from child process that is terminated already, see above + wait ${pid_slowpoke}; exit_slowpoke=$? + show_warning "Watched command finished with exit code $exit_slowpoke" + else + exit_slowpoke=${exit_force} + fi + exit ${exit_slowpoke} + +} + +main "$@" \ No newline at end of file diff --git a/ci/download_cli.sh b/ci/download_cli.sh index c271c95..de8e20d 100755 --- a/ci/download_cli.sh +++ b/ci/download_cli.sh @@ -13,7 +13,7 @@ then fi if [ -z "${APPSODY_CLI_FALLBACK}" ] then - APPSODY_CLI_FALLBACK=0.5.4 + APPSODY_CLI_FALLBACK=0.6.0 fi script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) diff --git a/ci/env.sh b/ci/env.sh index 0dab20f..d92bd0f 100755 --- a/ci/env.sh +++ b/ci/env.sh @@ -141,15 +141,11 @@ logged() { #expose an extension point for running before main 'env' processing exec_hooks $script_dir/ext/pre_env.d -#this is the default list of repos that we need to build index for -if [ -z "$REPO_LIST" ]; then - export REPO_LIST="experimental incubator stable" -fi - # image registry org for publishing stack if [ -z "$IMAGE_REGISTRY_ORG" ] then - export IMAGE_REGISTRY_ORG=appsody + echo "Error: Environment variable 'IMAGE_REGISTRY_ORG' is not set." + exit 1 fi # image registry for publishing stack