From 2bf06b092bb84f34925035de7779a565c6c08976 Mon Sep 17 00:00:00 2001 From: Leonard Jonathan Oh Date: Fri, 1 Dec 2023 03:08:06 +0000 Subject: [PATCH] Feature: Add support for custom functions in `./generate/functions` --- README.md | 90 +++++++++++-------- docs/examples/basic-functions/.gitlab-ci.yml | 66 ++++++++++++++ docs/examples/basic-functions/README.md | 7 ++ .../generate/definitions/FILES.ps1 | 4 + .../generate/definitions/VARIANTS.ps1 | 20 +++++ .../generate/functions/Download-Binary.ps1 | 10 +++ .../generate/functions/Download-Binary2.ps1 | 10 +++ .../generate/templates/.gitlab-ci.yml.ps1 | 75 ++++++++++++++++ .../generate/templates/Dockerfile.ps1 | 17 ++++ .../generate/templates/README.md.ps1 | 23 +++++ .../basic-functions/variants/curl/Dockerfile | 25 ++++++ ...-DockerImageVariants.Integration.Tests.ps1 | 48 +++++----- .../private/Get-ContentFromTemplate.Tests.ps1 | 17 ++++ .../private/Get-ContentFromTemplate.ps1 | 13 ++- .../private/Get-ContextFileContent.ps1 | 11 ++- .../private/Get-Function.Tests.ps1 | 31 +++++++ .../private/Get-Function.ps1 | 23 +++++ .../private/New-GenerateConfig.ps1 | 3 + .../private/New-GenerateFolder.Tests.ps1 | 8 +- .../private/New-GenerateFolder.ps1 | 22 ++++- .../private/New-RepositoryFile.ps1 | 7 +- ...ew-RepositoryVariantBuildContext.Tests.ps1 | 23 +++-- .../New-RepositoryVariantBuildContext.ps1 | 8 +- .../Generate-DockerImageVariants.Tests.ps1 | 9 ++ .../public/Generate-DockerImageVariants.ps1 | 14 ++- .../generate/functions/Download-Binary.ps1 | 9 ++ 26 files changed, 507 insertions(+), 86 deletions(-) create mode 100644 docs/examples/basic-functions/.gitlab-ci.yml create mode 100644 docs/examples/basic-functions/README.md create mode 100644 docs/examples/basic-functions/generate/definitions/FILES.ps1 create mode 100644 docs/examples/basic-functions/generate/definitions/VARIANTS.ps1 create mode 100644 docs/examples/basic-functions/generate/functions/Download-Binary.ps1 create mode 100644 docs/examples/basic-functions/generate/functions/Download-Binary2.ps1 create mode 100644 docs/examples/basic-functions/generate/templates/.gitlab-ci.yml.ps1 create mode 100644 docs/examples/basic-functions/generate/templates/Dockerfile.ps1 create mode 100644 docs/examples/basic-functions/generate/templates/README.md.ps1 create mode 100644 docs/examples/basic-functions/variants/curl/Dockerfile create mode 100644 src/Generate-DockerImageVariants/private/Get-Function.Tests.ps1 create mode 100644 src/Generate-DockerImageVariants/private/Get-Function.ps1 create mode 100644 src/Generate-DockerImageVariants/samples/generate/functions/Download-Binary.ps1 diff --git a/README.md b/README.md index 6cea9d8..ad1225b 100644 --- a/README.md +++ b/README.md @@ -53,74 +53,75 @@ If prompted to trust the repository, hit `Y` and `enter`. cd /path/to/my-project ``` -2. Initialize the `/generate` folder +1. Initialize the `./generate` folder ```powershell Import-Module Generate-DockerImageVariants Generate-DockerImageVariants . -Init ``` - Definition and template files are generated in the `/generate` folder. + Definition and template files are generated in the `./generate` folder. ```sh - . ├── generate │ ├── definitions │ │ ├── FILES.ps1 │ │ └── VARIANTS.ps1 + │ ├── functions + │ │ └── Download-Binary.ps1 │ └── templates │ ├── Dockerfile.ps1 │ └── README.md.ps1 ``` -3. Edit the definitions and template files in `/generate` (as needed) +1. Edit the definitions and template files in `./generate` (as needed) -4. Generate the variants: +1. Generate the variants: ```powershell Generate-DockerImageVariants . ``` - Build contexts of variants are generated in `/variants`. + Build contexts of variants are generated in `./variants`. The repository tree now looks like: ```sh - . + ├── README.md ├── generate │ ├── definitions │ │ ├── FILES.ps1 │ │ └── VARIANTS.ps1 + │ ├── functions + │ │ └── Download-Binary.ps1 │ └── templates │ ├── Dockerfile.ps1 │ └── README.md.ps1 - ├── README.md └── variants - └── some-tag-of-variant + └── curl └── Dockerfile ``` -## Generation definitions and templates +## Directory structure -A single folder named `/generate` at the base of the repository will hold all the definition and template files. - -- `/generate/definitions` is the definitions folder containing two files `VARIANTS.ps1` and `FILES.ps1` -- `/generate/templates` is the templates folder and create template files. E.g. `/generate/templates/Dockerfile.ps1`, `/generate/templates/README.md.ps1` +A single folder named `./generate` at the base of the repository will hold all the definition and template files: ```sh -. ├── generate -│ ├── definitions -│ │ ├── FILES.ps1 # An *optional* definition file for generation of repository files -│ │ └── VARIANTS.ps1 # Variant definition file for generation of variant build context -│ └── templates -│ ├── Dockerfile.ps1 # Dockerfile template (shared among variants across all distros) -│ └── README.md.ps1 # README.md template +│ ├── definitions # Definitions folder +│ │ ├── FILES.ps1 # An optional definition file for generation of repository files +│ │ └── VARIANTS.ps1 # Variant definition file for generation of variant build context +│ ├── functions # Functions folder (optional). Useful for Dockerfile templating +│ │ └── Some-Function.ps1 # A function to use in your templates +│ │ └── Another-Function.ps1 # A function to use in your templates +│ └── templates # Templates folder +│ ├── Dockerfile.ps1 # Dockerfile template (shared among variants across all distros) +│ └── README.md.ps1 # README.md template ``` ## Generation of a variant -At minimum, the `/generate/definitions/VARIANTS.ps1` definition file should contain the `$VARIANTS` definition like this: +At minimum, the `./generate/definitions/VARIANTS.ps1` definition file should contain the `$VARIANTS` definition like this: ```powershell $VARIANTS = @( @@ -151,10 +152,9 @@ $FILES = @( ) ``` -Upon generation, a file `/variants/sometag/Dockerfile` is generated in the `sometag` variant's build context in `/variants/sometag`, as well as a file `/README.md`, both relative to the base of the project. +Upon generation, the `sometag` variant's build context is generated in `./variants/sometag` with a file `Dockerfile`, as well as a file `./README.md`, both relative to the base of the project. ```sh -. ├── README.md └── variants | └── sometag @@ -163,6 +163,21 @@ Upon generation, a file `/variants/sometag/Dockerfile` is generated in the `some See [this](docs/examples/basic) basic example. +## Using custom functions + +To add a custom function, add a `.ps1` file in the `./generate/functions`. They will be dot-sourced and available in your templates. For instance, to add two functions `Some-Function` and `Another-Function`: + +```sh +├── generate +│ ├── functions # Functions is optional. Useful for Dockerfile templating +│ │ └── Some-Function.ps1 # A function to use in your templates +│ │ └── Another-Function.ps1 # A function to use in your templates +``` + +Then simply call them in your templates. + +See [this](docs/examples/basic-functions) basic example with function called `Download-Binary` and `Download-Binary2`. + ## Generation of multiple variants Suppose we want to generate two variants tagged `curl` and `git`: @@ -178,7 +193,7 @@ $VARIANTS = @( ) # This is a optional variable that sets a common buildContextFiles for all variants -# Individual variant buildContextsFiles takes precendence over this +# Individual variant buildContextsFiles overrides this $VARIANTS_SHARED = @{ buildContextFiles = @{ templates = @{ @@ -198,7 +213,6 @@ $VARIANTS_SHARED = @{ Upon generation, the `curl` and `git` variants' build contexts are generated: ```sh -. └── variants | └── curl | └── Dockerfile @@ -227,7 +241,7 @@ $VARIANTS = @( ) ``` -This will recursively copy all descending files/folders of the `/app` folder located relative to the *base* of the parent repository into the to-be-generated `curl` variant's build directory `/variants/curl` as `/variants/curl/app`. +This will recursively copy all descending files/folders of the `./app` folder located relative to the *base* of the parent repository into the to-be-generated `curl` variant's build directory `./variants/curl` as `./variants/curl/app`. See [this](docs/examples/basic-copies) example. @@ -295,9 +309,8 @@ $VARIANTS = @( The template pass to generate the variant's build context `Dockerfile` proceeds as such: -1. The template `/generate/templates/Dockerfile.ps1` is processed - -2. The file `/variants/curl-git/Dockerfile` is now generated in the `curl-git` variant's build context: `/variants/curl-git` +1. The template `./generate/templates/Dockerfile.ps1` is processed +1. The build context: `./variants/curl-git` is generated with the file `./variants/curl-git/Dockerfile` See [this](docs/examples/basic-component-chaining) example. @@ -336,7 +349,6 @@ $VARIANTS_SHARED = @{ Upon generation, **three** variants build contexts for variants `curl-git`, `curl`, and `git` are generated: ```sh -. └── variants | └── curl-git | └── Dockerfile @@ -353,11 +365,13 @@ To specify that only certain components be processed, independent of the `tag` p - [`/docs/examples/basic-custom-components`](docs/examples/basic-custom-components) example. - [`/docs/examples/basic-custom-components-distro`](docs/examples/basic-custom-components-distro) example. -**Note: If the variant's `tag` consist of a word that matches the variant's `distro`, `distro` will not be among the `components`.** For instance, in the above example, if the `tag` is `curl-git-alpine`, there will still only be two components `curl` and `git`. `alpine` will not be considered a component. +Note if using [`distro`](#appendix): + +> If [`distro`](#appendix) is non-empty, and if the variant's `tag` consist of a word that matches the variant's `distro`, `distro` will not be among the `components`.** For instance, in the above example, if the `tag` is `curl-git-alpine` and the distro is `alpine`, there will still only be two components `curl` and `git`. `alpine` will not be considered a component. ## Optional: Generate other repository files -To generate files other than variant build contexts in `/variants`, define them in `FILES.ps1`. +To generate files other than variant build contexts in `./variants`, define them in `FILES.ps1`. Suppose we want to generate `README.md`: @@ -367,10 +381,9 @@ $FILES = @( ) ``` -Then, create their templates in the `/generate/templates` directory: +Then, create their templates in the `./generate/templates` directory: ```sh -. ├── generate │ └── templates │ └── README.md.ps1 # README.md template @@ -379,7 +392,6 @@ Then, create their templates in the `/generate/templates` directory: Upon generation, `README.md` is now generated: ```sh -. └── README.md ``` @@ -395,7 +407,7 @@ A `$VARIANT` definition will contain these properties. The `buildContextFiles` property of the `$VARIANT` object can be used to customize the template processing: -- `common` - (Optional, defaults to `$false`) Specifies whether this file is shared by all distros. If value is `$true`, template has to be present in `/generate/templates/.ps1`. If value is `$false`, and if a variant `distro` is defined, template has to be present in `/generate/templates///`, or if a variant `distro` is omitted, template has to be present in `/generate/templates//.ps1`. +- `common` - (Optional, defaults to `$false`) Specifies whether this file is shared by all distros. If value is `$true`, template has to be present in `./generate/templates/.ps1`. If value is `$false`, and if a variant `distro` is defined, template has to be present in `./generate/templates///`, or if a variant `distro` is omitted, template has to be present in `./generate/templates//.ps1`. - `includeHeader` - (Optional, defaults to `$false`) Specifies to process a template `.header.ps1`. Template path determined by `common` - `includeFooter` - (Optional, defaults to `$false`) Specifies to process a template `.footer.ps1`. Template path determined by `common` - `passes` - (Mandatory) An array of pass definitions that the template will undergo. Each pass will generate a single file. @@ -410,8 +422,8 @@ $VARIANT = @{ # When the tag contains words delimited by '-', it known as component-chaining. tag = 'some-cool-tag' - # Specifies a distro (optional). If you dont define a distro, templates will be sourced from /generate/templates/ folder - # In contrast, if a distro is specified, templates will be sourced from /generate/templates// folder + # Specifies a distro (optional). If you dont define a distro, templates will be sourced from ./generate/templates/ folder + # In contrast, if a distro is specified, templates will be sourced from ./generate/templates// folder distro = 'somedistro' # Specifies that this variant should be tagged ':latest'. This property will be useful in generation of content in README.md or ci files. Automatically populated as $false if unspecified diff --git a/docs/examples/basic-functions/.gitlab-ci.yml b/docs/examples/basic-functions/.gitlab-ci.yml new file mode 100644 index 0000000..593bb6c --- /dev/null +++ b/docs/examples/basic-functions/.gitlab-ci.yml @@ -0,0 +1,66 @@ +image: docker:latest +services: + - docker:dind +variables: + DOCKER_DRIVER: overlay2 + +stages: + - build + +.build_template: &build_definition + stage: build + only: + refs: + - branches + - /^v(?:\d+\.)+\d+$/ + variables: + - $VARIANT_TAG + - $VARIANT_TAG_WITH_VERSION + - $VARIANT_BUILD_DIR + except: + refs: + - master + before_script: + - date '+%Y-%m-%d %H:%M:%S %z' + + # Login to Docker Hub registry + - echo "${DOCKERHUB_REGISTRY_PASSWORD}" | docker login -u "${DOCKERHUB_REGISTRY_USER}" --password-stdin + + # Login to GitLab registry + - echo "${CI_REGISTRY_PASSWORD}" | docker login -u "${CI_REGISTRY_USER}" --password-stdin "${CI_REGISTRY}" + + script: + - date '+%Y-%m-%d %H:%M:%S %z' + + - docker build + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_VERSION}" + -t "${CI_REGISTRY_IMAGE}:${VARIANT_TAG}" + -t "${CI_REGISTRY_IMAGE}:${VARIANT_TAG_WITH_VERSION}" + "${VARIANT_BUILD_DIR}" + + - date '+%Y-%m-%d %H:%M:%S %z' + + # Push to Docker Hub registry. E.g. 'namespace/my-project:tag' + - docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" + - docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_VERSION}" + + # Push to GitLab registry. E.g. 'registry.gitlab.com/namespace/my-project:tag + - docker push "${CI_REGISTRY_IMAGE}:${VARIANT_TAG}" + - docker push "${CI_REGISTRY_IMAGE}:${VARIANT_TAG_WITH_VERSION}" + + after_script: + - date '+%Y-%m-%d %H:%M:%S %z' + + # Log out of Docker Hub registry + - docker logout + + # Log out of GitLab registry + - docker logout "${CI_REGISTRY}" + +build-curl: + <<: *build_definition + variables: + VARIANT_TAG: curl + VARIANT_TAG_WITH_VERSION: curl-$CI_COMMIT_REF_NAME + VARIANT_BUILD_DIR: variants/curl diff --git a/docs/examples/basic-functions/README.md b/docs/examples/basic-functions/README.md new file mode 100644 index 0000000..23ef8df --- /dev/null +++ b/docs/examples/basic-functions/README.md @@ -0,0 +1,7 @@ +# basic + +## Tags + +| Tag | Dockerfile Build Context | +|:-------:|:---------:| +| `:curl` | [View](variants/curl ) | diff --git a/docs/examples/basic-functions/generate/definitions/FILES.ps1 b/docs/examples/basic-functions/generate/definitions/FILES.ps1 new file mode 100644 index 0000000..4591f9b --- /dev/null +++ b/docs/examples/basic-functions/generate/definitions/FILES.ps1 @@ -0,0 +1,4 @@ +$FILES = @( + '.gitlab-ci.yml' + 'README.md' +) diff --git a/docs/examples/basic-functions/generate/definitions/VARIANTS.ps1 b/docs/examples/basic-functions/generate/definitions/VARIANTS.ps1 new file mode 100644 index 0000000..a87980e --- /dev/null +++ b/docs/examples/basic-functions/generate/definitions/VARIANTS.ps1 @@ -0,0 +1,20 @@ +$VARIANTS = @( + @{ + tag = 'curl' + } +) + +$VARIANTS_SHARED = @{ + buildContextFiles = @{ + templates = @{ + 'Dockerfile' = @{ + common = $true + passes = @( + @{ + variables = @{} + } + ) + } + } + } +} diff --git a/docs/examples/basic-functions/generate/functions/Download-Binary.ps1 b/docs/examples/basic-functions/generate/functions/Download-Binary.ps1 new file mode 100644 index 0000000..9d05be2 --- /dev/null +++ b/docs/examples/basic-functions/generate/functions/Download-Binary.ps1 @@ -0,0 +1,10 @@ +function Download-Binary { +@" +# Install foo +RUN set -eux; \ + wget https://localhost/foo-linux-amd64; \ + mv foo-linux-amd64 /usr/local/bin/foo; \ + chmod +x /usr/local/bin/foo; \ + foo version +"@ +} diff --git a/docs/examples/basic-functions/generate/functions/Download-Binary2.ps1 b/docs/examples/basic-functions/generate/functions/Download-Binary2.ps1 new file mode 100644 index 0000000..65772bc --- /dev/null +++ b/docs/examples/basic-functions/generate/functions/Download-Binary2.ps1 @@ -0,0 +1,10 @@ +function Download-Binary2 { +@" +# Install bar +RUN set -eux; \ + wget https://localhost/bar-linux-amd64; \ + mv bar-linux-amd64 /usr/local/bin/bar; \ + chmod +x /usr/local/bin/bar; \ + bar version +"@ +} diff --git a/docs/examples/basic-functions/generate/templates/.gitlab-ci.yml.ps1 b/docs/examples/basic-functions/generate/templates/.gitlab-ci.yml.ps1 new file mode 100644 index 0000000..646c062 --- /dev/null +++ b/docs/examples/basic-functions/generate/templates/.gitlab-ci.yml.ps1 @@ -0,0 +1,75 @@ +@' +image: docker:latest +services: + - docker:dind +variables: + DOCKER_DRIVER: overlay2 + +stages: + - build + +.build_template: &build_definition + stage: build + only: + refs: + - branches + - /^v(?:\d+\.)+\d+$/ + variables: + - $VARIANT_TAG + - $VARIANT_TAG_WITH_VERSION + - $VARIANT_BUILD_DIR + except: + refs: + - master + before_script: + - date '+%Y-%m-%d %H:%M:%S %z' + + # Login to Docker Hub registry + - echo "${DOCKERHUB_REGISTRY_PASSWORD}" | docker login -u "${DOCKERHUB_REGISTRY_USER}" --password-stdin + + # Login to GitLab registry + - echo "${CI_REGISTRY_PASSWORD}" | docker login -u "${CI_REGISTRY_USER}" --password-stdin "${CI_REGISTRY}" + + script: + - date '+%Y-%m-%d %H:%M:%S %z' + + - docker build + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_VERSION}" + -t "${CI_REGISTRY_IMAGE}:${VARIANT_TAG}" + -t "${CI_REGISTRY_IMAGE}:${VARIANT_TAG_WITH_VERSION}" + "${VARIANT_BUILD_DIR}" + + - date '+%Y-%m-%d %H:%M:%S %z' + + # Push to Docker Hub registry. E.g. 'namespace/my-project:tag' + - docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" + - docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_VERSION}" + + # Push to GitLab registry. E.g. 'registry.gitlab.com/namespace/my-project:tag + - docker push "${CI_REGISTRY_IMAGE}:${VARIANT_TAG}" + - docker push "${CI_REGISTRY_IMAGE}:${VARIANT_TAG_WITH_VERSION}" + + after_script: + - date '+%Y-%m-%d %H:%M:%S %z' + + # Log out of Docker Hub registry + - docker logout + + # Log out of GitLab registry + - docker logout "${CI_REGISTRY}" + +'@ + +$( $VARIANTS | % { +@" + +build-$( $_['tag'] ): + <<: *build_definition + variables: + VARIANT_TAG: $( $_['tag'] ) + VARIANT_TAG_WITH_VERSION: $( $_['tag'] )-`$CI_COMMIT_REF_NAME + VARIANT_BUILD_DIR: $( $_['build_dir_rel'] ) + +"@ +}) diff --git a/docs/examples/basic-functions/generate/templates/Dockerfile.ps1 b/docs/examples/basic-functions/generate/templates/Dockerfile.ps1 new file mode 100644 index 0000000..47e7c85 --- /dev/null +++ b/docs/examples/basic-functions/generate/templates/Dockerfile.ps1 @@ -0,0 +1,17 @@ +@" +FROM alpine:3.8 + +echo "My tag is $( $VARIANT['tag'] )" + +# Install curl +RUN apk update \ + && apk add --no-cache \ + curl \ + && rm -rf /var/cache/apk/* + +$( Download-Binary ) + +$( Download-Binary2 ) + +CMD ["crond", "-f"] +"@ diff --git a/docs/examples/basic-functions/generate/templates/README.md.ps1 b/docs/examples/basic-functions/generate/templates/README.md.ps1 new file mode 100644 index 0000000..d08a821 --- /dev/null +++ b/docs/examples/basic-functions/generate/templates/README.md.ps1 @@ -0,0 +1,23 @@ +@" +# basic + +## Tags + +| Tag | Dockerfile Build Context | +|:-------:|:---------:| +$( +($VARIANTS | % { + if ( $_['tag_as_latest'] ) { +@" +| ``:$( $_['tag'] )``, ``:latest`` | [View](variants/$( $_['tag'] ) ) | + +"@ + }else { +@" +| ``:$( $_['tag'] )`` | [View](variants/$( $_['tag'] ) ) | + +"@ + } +}) -join '' +) +"@ diff --git a/docs/examples/basic-functions/variants/curl/Dockerfile b/docs/examples/basic-functions/variants/curl/Dockerfile new file mode 100644 index 0000000..585a341 --- /dev/null +++ b/docs/examples/basic-functions/variants/curl/Dockerfile @@ -0,0 +1,25 @@ +FROM alpine:3.8 + +echo "My tag is curl" + +# Install curl +RUN apk update \ + && apk add --no-cache \ + curl \ + && rm -rf /var/cache/apk/* + +# Install foo +RUN set -eux; \ + wget https://localhost/foo-linux-amd64; \ + mv foo-linux-amd64 /usr/local/bin/foo; \ + chmod +x /usr/local/bin/foo; \ + foo version + +# Install bar +RUN set -eux; \ + wget https://localhost/bar-linux-amd64; \ + mv bar-linux-amd64 /usr/local/bin/bar; \ + chmod +x /usr/local/bin/bar; \ + bar version + +CMD ["crond", "-f"] \ No newline at end of file diff --git a/src/Generate-DockerImageVariants/Generate-DockerImageVariants.Integration.Tests.ps1 b/src/Generate-DockerImageVariants/Generate-DockerImageVariants.Integration.Tests.ps1 index 4fc232a..bc3c5fd 100644 --- a/src/Generate-DockerImageVariants/Generate-DockerImageVariants.Integration.Tests.ps1 +++ b/src/Generate-DockerImageVariants/Generate-DockerImageVariants.Integration.Tests.ps1 @@ -1,6 +1,9 @@ Describe 'Generate-DockerImageVariants' -Tag 'Integration' { BeforeEach { + Get-Module Generate-DockerImageVariants | Remove-Module + Import-Module $PSScriptRoot 3>$null + $PROJECT_DIR = Convert-Path "$PSScriptRoot/../../" $DOCS_DIR = Join-Path $PROJECT_DIR 'docs' $DOCS_EXAMPLES_DIR = Join-Path $DOCS_DIR 'examples' @@ -19,20 +22,22 @@ Describe 'Generate-DockerImageVariants' -Tag 'Integration' { Context 'Parameters' { - It 'Initializes the /generate directory' { - # Expected folders + BeforeEach { $testProjectGenerateDir = Join-Path $testProjectDir 'generate' $testProjectGenerateDefinitionsDir = Join-Path $testProjectGenerateDir 'definitions' + $testProjectGenerateFunctionsDir = Join-Path $testProjectGenerateDir 'functions' $testProjectGenerateTemplatesDir = Join-Path $testProjectGenerateDir 'templates' - # Expected definition files + # Definition files $testProjectGenerateDefinitionsFiles = Join-Path $testProjectGenerateDefinitionsDir 'FILES.ps1' $testProjectGenerateDefinitionsVariants = Join-Path $testProjectGenerateDefinitionsDir 'VARIANTS.ps1' - # Expected templates files + # Templates files $testProjectGenerateTemplatesDockerfile = Join-Path $testProjectGenerateTemplatesDir 'Dockerfile.ps1' $testProjectGenerateTemplatesReadmeMd = Join-Path $testProjectGenerateTemplatesDir 'README.md.ps1' + } + It '-Init initializes the /generate directory' { Generate-DockerImageVariants -Init -ProjectPath $testProjectDir 6>&1 > $null $testProjectGenerateDir | Get-Item -Force | Should -BeOfType [System.IO.DirectoryInfo] @@ -47,19 +52,6 @@ Describe 'Generate-DockerImageVariants' -Tag 'Integration' { } It 'Does not override existing files in the /generate directory' { - # Expected folders - $testProjectGenerateDir = Join-Path $testProjectDir 'generate' - $testProjectGenerateDefinitionsDir = Join-Path $testProjectGenerateDir 'definitions' - $testProjectGenerateTemplatesDir = Join-Path $testProjectGenerateDir 'templates' - - # Expected definition files - $testProjectGenerateDefinitionsFiles = Join-Path $testProjectGenerateDefinitionsDir 'FILES.ps1' - $testProjectGenerateDefinitionsVariants = Join-Path $testProjectGenerateDefinitionsDir 'VARIANTS.ps1' - - # Expected templates files - $testProjectGenerateTemplatesDockerfile = Join-Path $testProjectGenerateTemplatesDir 'Dockerfile.ps1' - $testProjectGenerateTemplatesReadmeMd = Join-Path $testProjectGenerateTemplatesDir 'README.md.ps1' - # Create all folders, one definition file, one template file $testProjectGenerateDefinitionsFiles, $testProjectGenerateTemplatesDockerfile | % { @@ -76,19 +68,17 @@ Describe 'Generate-DockerImageVariants' -Tag 'Integration' { } It 'Should treat definition file FILES.ps1 as optional' { - # Expected folders - $testProjectGenerateDir = Join-Path $testProjectDir 'generate' - $testProjectGenerateDefinitionsDir = Join-Path $testProjectGenerateDir 'definitions' - $testProjectGenerateTemplatesDir = Join-Path $testProjectGenerateDir 'templates' - - # Expected definition files - $testProjectGenerateDefinitionsFiles = Join-Path $testProjectGenerateDefinitionsDir 'FILES.ps1' - Generate-DockerImageVariants -ProjectPath $testProjectDir -Init -ErrorAction Stop #6>$null Remove-Item $testProjectGenerateDefinitionsFiles Generate-DockerImageVariants -ProjectPath $testProjectDir -ErrorAction Stop 6>$null } + It 'Should treat functions as optional' { + Generate-DockerImageVariants -ProjectPath $testProjectDir -Init -ErrorAction Stop #6>$null + Remove-Item $testProjectGenerateFunctionsDir -Recurse -Force + Generate-DockerImageVariants -ProjectPath $testProjectDir -ErrorAction Stop 6>$null + } + It 'Should generate files for default prototypes created by -Init' { Generate-DockerImageVariants -ProjectPath $testProjectDir -Init -ErrorAction Stop #6>$null Generate-DockerImageVariants -ProjectPath $testProjectDir -ErrorAction Stop 6>$null @@ -97,6 +87,7 @@ Describe 'Generate-DockerImageVariants' -Tag 'Integration' { Test-Path $testProjectDir/variants/curl-git/Dockerfile | Should -Be $true Test-Path $testProjectDir/variants/my-cool-variant/Dockerfile | Should -Be $true } + It 'Should generate files for example: advanced-component-chaining-copies-variables' { { $exampleProjectPath = Join-Path $DOCS_EXAMPLES_DIR 'advanced-component-chaining-copies-variables' @@ -160,6 +151,13 @@ Describe 'Generate-DockerImageVariants' -Tag 'Integration' { Generate-DockerImageVariants -ProjectPath $exampleProjectPath -ErrorAction Stop 6>$null } | Should -Not -Throw } + It 'Should generate files for example: basic-functions' { + { + $exampleProjectPath = Join-Path $DOCS_EXAMPLES_DIR 'basic-functions' + + Generate-DockerImageVariants -ProjectPath $exampleProjectPath -ErrorAction Stop 6>$null + } | Should -Not -Throw + } It 'Should generate files for example: basic-multiple-variants' { { $exampleProjectPath = Join-Path $DOCS_EXAMPLES_DIR 'basic-multiple-variants' diff --git a/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.Tests.ps1 b/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.Tests.ps1 index 4d4cd9e..2fb05a3 100644 --- a/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.Tests.ps1 +++ b/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.Tests.ps1 @@ -6,9 +6,17 @@ Describe "Get-ContentFromTemplate" -Tag 'Unit' { BeforeEach { $drive = Convert-Path 'TestDrive:\' + $templateFileContent = "12345" $templateFile = Join-Path $drive 'template.ps1' $templateFileContent | Out-File $templateFile -Encoding utf8 -Force + + $functionsFile = Join-Path $drive 'functions.ps1' + @' +function Foo-Function { + 'output of Foo-Function' +} +'@ | Out-File $functionsFile -Encoding utf8 -Force } Context 'Behavior' { @@ -23,8 +31,17 @@ Describe "Get-ContentFromTemplate" -Tag 'Unit' { It 'Gets content from a template' { $content = Get-ContentFromTemplate -Path $templateFile + $content | Should -Be $templateFileContent + } + + It 'Gets content from a template with functions' { + $templateFileContent = "Foo-Function" + $templateFileContent | Out-File $templateFile -Encoding utf8 -Force + + $content = Get-ContentFromTemplate -Path $templateFile -Functions @( $functionsFile ) + $content | Should -Be 'output of Foo-Function' } It 'Prepends newlines to content from a template' { diff --git a/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.ps1 b/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.ps1 index 90c3dd4..04155ca 100644 --- a/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.ps1 +++ b/src/Generate-DockerImageVariants/private/Get-ContentFromTemplate.ps1 @@ -6,6 +6,11 @@ function Get-ContentFromTemplate { , [ValidateRange(1,100)] [int]$PrependNewLines + , + [Parameter(ParameterSetName='default')] + [ValidateNotNull()] + [string[]] + $Functions ) try { @@ -13,7 +18,13 @@ function Get-ContentFromTemplate { throw "No such file: $Path" } - $content = & $Path + $content = & { + foreach ($f in $Functions) { + "Sourcing function: $f" | Write-Verbose + . $f + } + & $Path + } if ($PrependNewLines -gt 0) { $content = "$( "`n" * $PrependNewLines )$content" } diff --git a/src/Generate-DockerImageVariants/private/Get-ContextFileContent.ps1 b/src/Generate-DockerImageVariants/private/Get-ContextFileContent.ps1 index ed4475b..c27e770 100644 --- a/src/Generate-DockerImageVariants/private/Get-ContextFileContent.ps1 +++ b/src/Generate-DockerImageVariants/private/Get-ContextFileContent.ps1 @@ -4,6 +4,11 @@ function Get-ContextFileContent { [Parameter()] [ValidateNotNullOrEmpty()] [hashtable]$Template + , + [Parameter()] + [ValidateNotNull()] + [string[]] + $Functions , [Parameter()] [hashtable]$TemplatePassVariables @@ -17,11 +22,13 @@ function Get-ContextFileContent { # Make PASS_VARIABLES global variable available to the template script $global:PASS_VARIABLES = if ($TemplatePassVariables) { $TemplatePassVariables } else { @{} } - $params = @{} + $params = @{ + Functions = $Functions + } if ( $Template['includeHeader'] ) { $templateFileAbsolutePath = [IO.Path]::Combine($Template['templateDirectory'], "$( $Template['file'] ).header.ps1") "Processing template file: $templateFileAbsolutePath" | Write-Verbose - Get-ContentFromTemplate -Path $templateFileAbsolutePath + Get-ContentFromTemplate -Path $templateFileAbsolutePath @params # Spaces our header from body $params['PrependNewLines'] = 2 diff --git a/src/Generate-DockerImageVariants/private/Get-Function.Tests.ps1 b/src/Generate-DockerImageVariants/private/Get-Function.Tests.ps1 new file mode 100644 index 0000000..5d8e773 --- /dev/null +++ b/src/Generate-DockerImageVariants/private/Get-Function.Tests.ps1 @@ -0,0 +1,31 @@ +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' +. "$here\$sut" + +Describe "Get-Function" -Tag 'Unit' { + + BeforeEach { + $drive = Convert-Path 'TestDrive:\' + $definitionFile = Join-Path $drive 'foo.ps1' + New-Item $definitionFile -ItemType File -Force + } + + Context 'Behavior' { + + It 'Should throw on errors' { + '{' | Out-File $definitionFile -Encoding utf8 -Force -Append + + { + Get-Function -Path $definitionFile 2>$null + } | Should -Throw + } + + It 'Returns path of file' { + $f = Get-Function -Path $definitionFile + + $f | Should -Be $definitionFile + } + + } + +} diff --git a/src/Generate-DockerImageVariants/private/Get-Function.ps1 b/src/Generate-DockerImageVariants/private/Get-Function.ps1 new file mode 100644 index 0000000..449a250 --- /dev/null +++ b/src/Generate-DockerImageVariants/private/Get-Function.ps1 @@ -0,0 +1,23 @@ +function Get-Function { + [CmdletBinding()] + param ( + # Path to the function file + [Parameter(Mandatory)] + [ValidateScript({ Test-Path $_ })] + [object] + $Path + ) + try { + & { + # Test the syntax and throw on errors + "Reading file: $Path" | Write-Verbose + . $Path *> $null + + # Normalize path + Convert-Path $Path + } + }catch { + Write-Error "There was an error in function file $Path. Exception: $( $_.Exception.Message )" -ErrorAction Continue + throw + } +} diff --git a/src/Generate-DockerImageVariants/private/New-GenerateConfig.ps1 b/src/Generate-DockerImageVariants/private/New-GenerateConfig.ps1 index b49195c..ac11808 100644 --- a/src/Generate-DockerImageVariants/private/New-GenerateConfig.ps1 +++ b/src/Generate-DockerImageVariants/private/New-GenerateConfig.ps1 @@ -20,12 +20,14 @@ function New-GenerateConfig { $GenerateConfig['MODULE_SAMPLES_GENERATE_DEFINITIONS_DIR'] = Join-Path $GenerateConfig['MODULE_SAMPLES_GENERATE_DIR'] 'definitions' # $GenerateConfig['MODULE_SAMPLES_GENERATE_DEFINITIONS_FILES_FILE'] = Join-Path $GenerateConfig['MODULE_SAMPLES_GENERATE_DEFINITIONS_DIR'] 'FILES.ps1' # $GenerateConfig['MODULE_SAMPLES_GENERATE_DEFINITIONS_VARIANTS_FILE'] = Join-Path $GenerateConfig['MODULE_SAMPLES_GENERATE_DEFINITIONS_DIR'] 'VARIANTS.ps1' + $GenerateConfig['MODULE_SAMPLES_GENERATE_FUNCTIONS_DIR'] = Join-Path $GenerateConfig['MODULE_SAMPLES_GENERATE_DIR'] 'functions' $GenerateConfig['MODULE_SAMPLES_GENERATE_TEMPLATES_DIR'] = Join-Path $GenerateConfig['MODULE_SAMPLES_GENERATE_DIR'] 'templates' # Target repository paths $GenerateConfig['REPOSITORY_BASE_DIR'] = Resolve-Path $TargetRepositoryPath | Select-Object -ExpandProperty Path $GenerateConfig['GENERATE_BASE_DIR'] = Join-Path $GenerateConfig['REPOSITORY_BASE_DIR'] 'generate' $GenerateConfig['GENERATE_DEFINITIONS_DIR'] = Join-Path $GenerateConfig['GENERATE_BASE_DIR'] "definitions" + $GenerateConfig['GENERATE_FUNCTIONS_DIR'] = Join-Path $GenerateConfig['GENERATE_BASE_DIR'] "functions" $GenerateConfig['GENERATE_DEFINITIONS_VARIANTS_FILE'] = Join-Path $GenerateConfig['GENERATE_DEFINITIONS_DIR'] 'VARIANTS.ps1' $GenerateConfig['GENERATE_DEFINITIONS_FILES_FILE'] = Join-Path $GenerateConfig['GENERATE_DEFINITIONS_DIR'] 'FILES.ps1' $GenerateConfig['GENERATE_TEMPLATES_DIR'] = Join-Path $GenerateConfig['GENERATE_BASE_DIR'] "templates" @@ -34,6 +36,7 @@ function New-GenerateConfig { $GenerateConfig['VARIANTS'] = @() $GenerateConfig['VARIANTS_SHARED'] = @{} $GenerateConfig['FILES'] = @() + $GenerateConfig['FUNCTIONS'] = @() $GenerateConfig } diff --git a/src/Generate-DockerImageVariants/private/New-GenerateFolder.Tests.ps1 b/src/Generate-DockerImageVariants/private/New-GenerateFolder.Tests.ps1 index d784791..d93fb01 100644 --- a/src/Generate-DockerImageVariants/private/New-GenerateFolder.Tests.ps1 +++ b/src/Generate-DockerImageVariants/private/New-GenerateFolder.Tests.ps1 @@ -8,9 +8,11 @@ Describe "New-GenerationFolder" -Tag 'Unit' { $GenerateConfig = @{ GENERATE_BASE_DIR = 'foo' GENERATE_DEFINITIONS_DIR = 'bar' - GENERATE_TEMPLATES_DIR = 'baz' - MODULE_SAMPLES_GENERATE_DEFINITIONS_DIR = 'foobar' - MODULE_SAMPLES_GENERATE_TEMPLATES_DIR = 'foobaz' + GENERATE_FUNCTIONS_DIR = 'bar' + GENERATE_TEMPLATES_DIR = 'bar' + MODULE_SAMPLES_GENERATE_DEFINITIONS_DIR = 'baz' + MODULE_SAMPLES_GENERATE_FUNCTIONS_DIR = 'baz' + MODULE_SAMPLES_GENERATE_TEMPLATES_DIR = 'baz' } } diff --git a/src/Generate-DockerImageVariants/private/New-GenerateFolder.ps1 b/src/Generate-DockerImageVariants/private/New-GenerateFolder.ps1 index 5540cba..8c3306d 100644 --- a/src/Generate-DockerImageVariants/private/New-GenerateFolder.ps1 +++ b/src/Generate-DockerImageVariants/private/New-GenerateFolder.ps1 @@ -7,8 +7,8 @@ function New-GenerationFolder { $GenerateConfig ) - # Create target repository definitions and templates folders - $GenerateConfig['GENERATE_BASE_DIR'], $GenerateConfig['GENERATE_DEFINITIONS_DIR'], $GenerateConfig['GENERATE_TEMPLATES_DIR'] | % { + # Create repository definitions and templates folders + $GenerateConfig['GENERATE_BASE_DIR'], $GenerateConfig['GENERATE_DEFINITIONS_DIR'], $GenerateConfig['GENERATE_FUNCTIONS_DIR'], $GenerateConfig['GENERATE_TEMPLATES_DIR'] | % { $destinationFullName = $_ if (Test-Path -LiteralPath $destinationFullName) { "Not creating folder $destinationFullName because a file or folder already exists with that name." | Write-Host -ForegroundColor Magenta @@ -18,7 +18,7 @@ function New-GenerationFolder { } } - # Create target repository definition files + # Create repository definition files Get-ChildItem $GenerateConfig['MODULE_SAMPLES_GENERATE_DEFINITIONS_DIR'] -Include '*.ps1' -Recurse -Force | % { $sourceItem = $_ $destinationFullName = Join-Path $GenerateConfig['GENERATE_DEFINITIONS_DIR'] $sourceItem.Name @@ -32,7 +32,21 @@ function New-GenerationFolder { } } - # Create target repository template files based on module's samples + # Create repository functions files + Get-ChildItem $GenerateConfig['MODULE_SAMPLES_GENERATE_FUNCTIONS_DIR'] -Include '*.ps1' -Recurse -Force | % { + $sourceItem = $_ + $destinationFullName = Join-Path $GenerateConfig['GENERATE_FUNCTIONS_DIR'] $sourceItem.Name + if (Test-Path -LiteralPath $destinationFullName) { + "Not creating functions file $destinationFullName because a file or folder already exists with that name." | Write-Host -ForegroundColor Magenta + }else { + "Creating functions file $destinationFullName" | Write-Host -ForegroundColor Green + if ($item = New-Item $destinationFullName -ItemType File) { + Get-Content $sourceItem.FullName -Force | Out-File $item.FullName -Encoding utf8 -Force + } + } + } + + # Create repository template files based on module's samples Get-ChildItem $GenerateConfig['MODULE_SAMPLES_GENERATE_TEMPLATES_DIR'] -Include '*.ps1' -Recurse -Force | % { $sourceItem = $_ $destinationFullName = Join-Path $GenerateConfig['GENERATE_TEMPLATES_DIR'] $sourceItem.Name diff --git a/src/Generate-DockerImageVariants/private/New-RepositoryFile.ps1 b/src/Generate-DockerImageVariants/private/New-RepositoryFile.ps1 index 5067df5..3cff090 100644 --- a/src/Generate-DockerImageVariants/private/New-RepositoryFile.ps1 +++ b/src/Generate-DockerImageVariants/private/New-RepositoryFile.ps1 @@ -5,6 +5,11 @@ function New-RepositoryFile { [ValidateNotNullOrEmpty()] [object] $File + , + [Parameter()] + [ValidateNotNull()] + [string[]] + $Functions , [Parameter(ParameterSetName='pipeline',ValueFromPipeline)] [ValidateNotNullOrEmpty()] @@ -29,7 +34,7 @@ function New-RepositoryFile { "Processing template file: $($File.templateFile)" | Write-Verbose - $content = Get-ContentFromTemplate -Path $File.templateFile -ErrorAction Stop + $content = Get-ContentFromTemplate -Path $File.templateFile -Functions $Functions -ErrorAction Stop $content | Out-File $File.file -Encoding utf8 -NoNewline -Force } } diff --git a/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.Tests.ps1 b/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.Tests.ps1 index 6fa314f..1d176a1 100644 --- a/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.Tests.ps1 +++ b/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.Tests.ps1 @@ -6,8 +6,21 @@ Describe "New-RepositoryVariantBuildContext" -Tag 'Unit' { BeforeEach { function Get-ContextFileContent {} + Mock Get-ContextFileContent { 'some content' } + function Test-Path {} + Mock Test-Path { $false } function New-Item {} - function Out-File {} + Mock New-Item {} + function Set-Content {} + Mock Set-Content { + param ( + [string]$Path, + [string]$Value + ) + if ($Value -ne (Get-ContextFileContent)) { + throw + } + } } Context 'Parameters' { @@ -17,8 +30,6 @@ Describe "New-RepositoryVariantBuildContext" -Tag 'Unit' { tag = 'foo' build_dir = '/path/to/repo/foo' } - Mock Test-Path { $false } - Mock New-Item {} $variant | New-RepositoryVariantBuildContext 6>$null @@ -35,8 +46,6 @@ Describe "New-RepositoryVariantBuildContext" -Tag 'Unit' { tag = 'foo' build_dir = '/path/to/repo/foo' } - Mock Test-Path { $false } - Mock New-Item {} New-RepositoryVariantBuildContext -Variant $variant 6>$null @@ -65,14 +74,12 @@ Describe "New-RepositoryVariantBuildContext" -Tag 'Unit' { } } Mock Test-Path { $true } - Mock Get-ContextFileContent { 'some content' } Mock New-Item { $true } - Mock Out-File {} New-RepositoryVariantBuildContext -Variant $variant 6>$null Assert-MockCalled New-Item -Times 1 -Scope It - Assert-MockCalled Out-File -Times 1 -Scope It + Assert-MockCalled Set-Content -Times 1 -Scope It } It "Creates files from copies" { diff --git a/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.ps1 b/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.ps1 index 8afa7a1..1a9416d 100644 --- a/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.ps1 +++ b/src/Generate-DockerImageVariants/private/New-RepositoryVariantBuildContext.ps1 @@ -5,6 +5,11 @@ function New-RepositoryVariantBuildContext { [ValidateNotNullOrEmpty()] [object] $Variant + , + [Parameter()] + [ValidateNotNull()] + [string[]] + $Functions , [Parameter(ParameterSetName='pipeline',ValueFromPipeline)] [ValidateNotNullOrEmpty()] @@ -33,6 +38,7 @@ function New-RepositoryVariantBuildContext { $params = @{ Template = $template TemplatePassVariables = $pass['variables'] + Functions = $Functions } "Generating build context file: $( $pass['file'] )" | Write-Verbose $content = & { @@ -43,7 +49,7 @@ function New-RepositoryVariantBuildContext { Get-ContextFileContent @params } New-Item $pass['file'] -ItemType File -Force > $null - $content | Out-File $pass['file'] -Encoding Utf8 -NoNewline -Force + Set-Content -Value $content -Path $pass['file'] -Encoding Utf8 -NoNewline -Force } } } diff --git a/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.Tests.ps1 b/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.Tests.ps1 index 4616cb9..02f5e1c 100644 --- a/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.Tests.ps1 +++ b/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.Tests.ps1 @@ -8,6 +8,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { function New-GenerateConfig {} function New-GenerationFolder {} function Get-Definition {} + function Get-Function {} function Get-VariantsPrototype {} function Get-FilesPrototype {} @@ -41,6 +42,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} # FILES = @() @@ -62,6 +64,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} # FILES = @() @@ -83,6 +86,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} # FILES = @() @@ -104,6 +108,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} # FILES = @() @@ -125,6 +130,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} FILES = @( @@ -148,6 +154,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} FILES = @( @@ -183,6 +190,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @( @{ tag = 'foo' @@ -207,6 +215,7 @@ Describe "Generate-DockerImageVariants" -Tag 'Unit' { $GenerateConfig = [ordered]@{ GENERATE_DEFINITIONS_VARIANTS_FILE = 'variants.ps1' GENERATE_DEFINITIONS_FILES_FILE = 'files.ps1' + GENERATE_FUNCTIONS_DIR = 'functions' VARIANTS = @() # VARIANTS_SHARED = @{} FILES = @( diff --git a/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.ps1 b/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.ps1 index 98580dd..9f63e0d 100644 --- a/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.ps1 +++ b/src/Generate-DockerImageVariants/public/Generate-DockerImageVariants.ps1 @@ -14,6 +14,7 @@ function Generate-DockerImageVariants { $ProjectPath ) process { + Set-StrictMode -Version Latest try { # Create the Config $GenerateConfig = New-GenerateConfig -ModulePath (Convert-Path $PSScriptRoot/..) -TargetRepositoryPath $ProjectPath @@ -43,6 +44,15 @@ function Generate-DockerImageVariants { } } + # Get functions (optional) + if ( Test-Path $GenerateConfig['GENERATE_FUNCTIONS_DIR'] -PathType Container ) { + $GenerateConfig['FUNCTIONS'] = @( + Get-ChildItem $GenerateConfig['GENERATE_FUNCTIONS_DIR'] -Recurse -Include '*.ps1' | % { + Get-Function -Path $_.FullName + } + ) + } + # Validate the VARIANTS and FILES defintion objects "Validating `$VARIANTS definition" | Write-Verbose Validate-Object -Prototype (Get-VariantsPrototype) -TargetObject $GenerateConfig['VARIANTS'] -Mandatory:$false @@ -57,11 +67,11 @@ function Generate-DockerImageVariants { # Make VARIANTS global variable available to the template script $global:VARIANTS = $GenerateConfig['VARIANTS'] - $GenerateConfig['VARIANTS'] | New-RepositoryVariantBuildContext + $GenerateConfig['VARIANTS'] | New-RepositoryVariantBuildContext -Functions $GenerateConfig['FUNCTIONS'] } # Generate other repo files. E.g. README.md - $GenerateConfig['FILES'] | New-RepositoryFile + $GenerateConfig['FILES'] | New-RepositoryFile -Functions $GenerateConfig['FUNCTIONS'] } }catch { "Ended with errors. Please review." | Write-Host -ForegroundColor Yellow diff --git a/src/Generate-DockerImageVariants/samples/generate/functions/Download-Binary.ps1 b/src/Generate-DockerImageVariants/samples/generate/functions/Download-Binary.ps1 new file mode 100644 index 0000000..dbd9b2a --- /dev/null +++ b/src/Generate-DockerImageVariants/samples/generate/functions/Download-Binary.ps1 @@ -0,0 +1,9 @@ +function Download-Binary { +@" +# RUN set -eux; \ +# wget https://localhost/foo-linux-amd64; \ +# mv foo-linux-amd64 /usr/local/bin/foo; \ +# chmod +x /usr/local/bin/foo; \ +# foo version +"@ +}