Skip to content

Commit

Permalink
Add new line before the content of each script file (fixes #126)
Browse files Browse the repository at this point in the history
Merge pull request #127 from johlju/f/issue-126
  • Loading branch information
Jaykul committed Jan 17, 2024
2 parents d183d88 + 7d9e7da commit f7dffc8
Show file tree
Hide file tree
Showing 21 changed files with 341 additions and 132 deletions.
5 changes: 5 additions & 0 deletions .earthlyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# ignore Modules (because we output there now)
/Modules/*
# These aren't part of the module (yet)
/PotentialContribution/*
/Content/*
100 changes: 60 additions & 40 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,55 +1,62 @@
name: Build on push
on: [push]
name: CI

on:
push: {}
pull_request:
branches: [ main ]

jobs:
build:
runs-on: windows-latest
runs-on: ubuntu-latest
env:
FORCE_COLOR: 1
steps:
- name: Checkout
uses: actions/checkout@v2
- name: GitVersion
id: gitversion
uses: PoshCode/Actions/gitversion@v1
- name: Install-RequiredModules
uses: PoshCode/Actions/install-requiredmodules@v1
- name: Build Module
id: build
uses: PoshCode/actions/build-module@v1
- uses: earthly/actions-setup@v1
with:
path: ${{github.workspace}}/Source
version: ${{ steps.gitversion.outputs.LegacySemVerPadded }}
destination: ${{github.workspace}}/output
- name: Upload Build Output
uses: actions/upload-artifact@v2
github-token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0

- name: earthly +test
if: github.ref != 'refs/heads/main'
run: earthly --strict +test

- name: earthly +push
if: github.ref == 'refs/heads/main'
run: earthly --push --secret NUGET_API_KEY --secret PSGALLERY_API_KEY --strict +all
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }}

- uses: actions/upload-artifact@v4
with:
name: ModuleBuilder
path: Modules/ModuleBuilder

- uses: actions/upload-artifact@v4
with:
name: TestResults
path: Modules/ModuleBuilder-TestResults

- uses: actions/upload-artifact@v4
with:
name: Modules
path: ${{github.workspace}}/output
name: Packages
path: Modules/ModuleBuilder-Packages

- name: Upload Tests
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: PesterTests
path: ${{github.workspace}}/Tests
- name: Upload RequiredModules.psd1
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: RequiredModules
path: ${{github.workspace}}/RequiredModules.psd1
- name: Upload PSScriptAnalyzerSettings.psd1
uses: actions/upload-artifact@v2
with:
name: ScriptAnalyzer
path: ${{github.workspace}}/PSScriptAnalyzerSettings.psd1
lint:
needs: build
name: Run PSScriptAnalyzer
runs-on: ubuntu-latest
steps:
- name: Download Build Output
uses: actions/download-artifact@v2
- name: Invoke-ScriptAnalyzer
uses: devblackops/github-action-psscriptanalyzer@master
with:
rootPath: Modules/ModuleBuilder
repoToken: ${{ secrets.GITHUB_TOKEN }}
test:
needs: build
runs-on: ${{ matrix.os }}
Expand All @@ -59,7 +66,20 @@ jobs:
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- name: Download Build Output
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: ModuleBuilder
path: Modules/ModuleBuilder
- name: Download Pester Tests
uses: actions/download-artifact@v4
with:
name: PesterTests
path: PesterTests
- name: Download RequiredModules
uses: actions/download-artifact@v4
with:
name: RequiredModules

- uses: PoshCode/Actions/install-requiredmodules@v1
- uses: PoshCode/Actions/pester@v1
with:
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Ignore version number folders and "output" where we build
# All of these folders are (or were) build outputs
[0-9]*/
obj/
Modules/
Output/
obj/
Tools/
coverage.xml
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"powershell.codeFormatting.alignPropertyValuePairs": true,
"powershell.codeFormatting.autoCorrectAliases": true,
"powershell.codeFormatting.useCorrectCasing": true,
"powershell.scriptAnalysis.settingsPath": "ScriptAnalyzerSettings.psd1",
"files.associations": {
"*.ps1xml": "xml"
"*.ps1xml": "xml",
".earthlyignore": "ignore"
}
}
68 changes: 68 additions & 0 deletions Build.build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<#
.SYNOPSIS
./project.build.ps1
.EXAMPLE
Invoke-Build
.NOTES
0.5.0 - Parameterize
Add parameters to this script to control the build
#>
[CmdletBinding()]
param(
# dotnet build configuration parameter (Debug or Release)
[ValidateSet('Debug', 'Release')]
[string]$Configuration = 'Release',

# Add the clean task before the default build
[switch]$Clean,

# Collect code coverage when tests are run
[switch]$CollectCoverage,

# Which projects to build
[Alias("Projects")]
$dotnetProjects = @(),

# Which projects are test projects
[Alias("TestProjects")]
$dotnetTestProjects = @(),

# Further options to pass to dotnet
[Alias("Options")]
$dotnetOptions = @{
"-verbosity" = "minimal"
# "-runtime" = "linux-x64"
}
)
$InformationPreference = "Continue"
$ErrorView = 'DetailedView'

# The name of the module to publish
$script:PSModuleName = "TerminalBlocks"
# Use Env because Earthly can override it
$Env:OUTPUT_ROOT ??= Join-Path $BuildRoot Modules

$Tasks = "Tasks", "../Tasks", "../../Tasks" | Convert-Path -ErrorAction Ignore | Select-Object -First 1
Write-Information "$($PSStyle.Foreground.BrightCyan)Found shared tasks in $Tasks" -Tag "InvokeBuild"
## Self-contained build script - can be invoked directly or via Invoke-Build
if ($MyInvocation.ScriptName -notlike '*Invoke-Build.ps1') {
& "$Tasks/_Bootstrap.ps1"

Invoke-Build -File $MyInvocation.MyCommand.Path @PSBoundParameters -Result Result

if ($Result.Error) {
$Error[-1].ScriptStackTrace | Out-String
exit 1
}
exit 0
}

## The first task defined is the default task. Put the right values for your project type here...
if ($dotnetProjects -and $Clean) {
Add-BuildTask CleanBuild Clean, ($Task ?? "Test")
} elseif ($Clean) {
Add-BuildTask CleanBuild Clean, ($Task ?? "Test")
}

## Initialize the build variables, and import shared tasks, including DotNet tasks
. "$Tasks/_Initialize.ps1"
66 changes: 66 additions & 0 deletions Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
VERSION 0.7
IMPORT github.com/poshcode/tasks
FROM mcr.microsoft.com/dotnet/sdk:7.0
WORKDIR /work

ARG --global EARTHLY_GIT_ORIGIN_URL
ARG --global EARTHLY_BUILD_SHA
ARG --global EARTHLY_GIT_BRANCH
# These are my common paths, used in my shared /Tasks repo
ARG --global OUTPUT_ROOT=/Modules
ARG --global TEST_ROOT=/Tests
ARG --global TEMP_ROOT=/temp
# These are my common build args, used in my shared /Tasks repo
ARG --global MODULE_NAME=ModuleBuilder
ARG --global CONFIGURATION=Release


worker:
# Dotnet tools and scripts installed by PSGet
ENV PATH=$HOME/.dotnet/tools:$HOME/.local/share/powershell/Scripts:$PATH
RUN mkdir /Tasks \
&& git config --global user.email "Jaykul@HuddledMasses.org" \
&& git config --global user.name "Earthly Build"
# I'm using Invoke-Build tasks from this other repo which rarely changes
COPY tasks+tasks/* /Tasks
# Dealing with dependencies first allows docker to cache packages for us
# So the dependency cach only re-builds when you add a new dependency
COPY RequiredModules.psd1 .
# COPY *.csproj .
RUN ["pwsh", "-File", "/Tasks/_Bootstrap.ps1", "-RequiredModulesPath", "RequiredModules.psd1"]

build:
FROM +worker
RUN mkdir $OUTPUT_ROOT $TEST_ROOT $TEMP_ROOT
COPY . .
# make sure you have bin and obj in .earthlyignore, as their content from context might cause problems
RUN ["pwsh", "-Command", "Invoke-Build", "-Task", "Build", "-File", "Build.build.ps1"]

# SAVE ARTIFACT [--keep-ts] [--keep-own] [--if-exists] [--force] <src> [<artifact-dest-path>] [AS LOCAL <local-path>]
SAVE ARTIFACT $OUTPUT_ROOT/$MODULE_NAME AS LOCAL ./Modules/$MODULE_NAME

test:
# If we run a target as a reference in FROM or COPY, it's outputs will not be produced
BUILD +build
FROM +build
# make sure you have bin and obj in .earthlyignore, as their content from context might cause problems
RUN ["pwsh", "-Command", "Invoke-Build", "-Task", "Test", "-File", "Build.build.ps1"]

# SAVE ARTIFACT [--keep-ts] [--keep-own] [--if-exists] [--force] <src> [<artifact-dest-path>] [AS LOCAL <local-path>]
SAVE ARTIFACT $TEST_ROOT AS LOCAL ./Modules/$MODULE_NAME-TestResults

# pack:
# BUILD +test # So that we get the module artifact from build too
# FROM +test
# RUN ["pwsh", "-Command", "Invoke-Build", "-Task", "Pack", "-File", "Build.build.ps1", "-Verbose"]
# SAVE ARTIFACT $OUTPUT_ROOT/publish/*.nupkg AS LOCAL ./Modules/$MODULE_NAME-Packages/

push:
FROM +build
RUN --push --secret NUGET_API_KEY --secret PSGALLERY_API_KEY -- \
pwsh -Command Invoke-Build -Task Push -File Build.build.ps1 -Verbose

all:
# BUILD +build
BUILD +test
BUILD +push
47 changes: 14 additions & 33 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,43 @@ This module is the first concrete step in the project (although it currently con

### Building from source

[![Build Status](https://poshcode.visualstudio.com/ModuleBuilder/_apis/build/status/ModuleBuilder)](https://poshcode.visualstudio.com/ModuleBuilder/_build/latest?definitionId=1)
[![Build Status](https://github.com/PoshCode/ModuleBuilder/actions/workflows/build.yml/badge.svg)](https://github.com/PoshCode/ModuleBuilder/actions/workflows/build.yml)

#### 1. Get the source, obviously
The easiest, fastest build uses [earthly](https://docs.earthly.dev/). Earthly builds use containers to ensure tools are available, and to cache their output. On Windows, it requires WSL2, Docker Desktop, and of course, the earthly CLI. If you already have those installed, you can just check out this repository and run `earthly +test` to build and run the tests.

```powershell
git clone https://github.com/PoshCode/ModuleBuilder.git
cd Modulebuilder
earthly +test
```

#### 2. Install dependencies
#### Building without earthly

We have a few modules which are required for building. They're listed in `RequiredModules.psd1` -- the `Install-RequiredModule` script installs them (it defaults to CurrentUser scope, but has a `-Scope` parameter if you're running elevated and want to install them for the `AllUsers`). They only change rarely, so you shouldn't need to run this repeatedly, but it does _import_ the modules too, so if you need to use newer versions of these modules (like Pester 5), you can use this to import the ones we need:
The full ModuleBuilder build has a lot of dependencies which are handled _for you_, in the Earthly build, like dotnet, gitversion, and several PowerShell modules. To build without it you will need to clone the PoshCode shared "Tasks" repository which contains shared Invoke-Build tasks into the same parent folder, so that the `Tasks` folder is a sibling of the `ModuleBuilder` folder:

```powershell
./Install-RequiredModule.ps1
git clone https://github.com/PoshCode/ModuleBuilder.git
git clone https://github.com/PoshCode/Tasks.git
```

#### 3. Run the `build.ps1` script.

By default, the build script uses [gitversion](/gittols/gitversion) to calculate the version of the build automatically, and will put the build in a folder like "ModuleBuilder\2.0.0" where 2.0.0 is the current version number.
As long as you have dotnet preinstalled, the `Build.build.ps1` script will use the shared [Tasks\_Bootstrap.ps1](https://github.com/PoshCode/Tasks/blob/main/_Bootstrap.ps1) to install the other dependencies (see [RequiredModules.psd1](https://github.com/PoshCode/ModuleBuilder/blob/main/RequiredModules.psd1)) and will then use [Invoke-Build](https://github.com/nightroman/Invoke-Build) and [Pester](https://github.com/Pester/Pester) to build and test the module.

```powershell
./build.ps1
cd Modulebuilder
./Build.build.ps1
```

If you don't have `gitversion` handy, you can just specify a version for the `-Semver` parameter:

```powershell
./build.ps1 -Semver 2.1.0-beta
```
This _should_ work on Windows, Linux, and MacOS, but I only test the process on Windows, and in the Linux containers via earthly.

#### 4. Run tests with Pester
#### The old-fashioned way

The `test.ps1` script runs Pester and ScriptAnalyzer. It finds the build output from our `build.ps1` script in the default build output location -- that is, right next to these scripts in the root of the repository. It actually removes the `ModuleBuilder` module and re-imports the highest version in that root:
You _can_ build the module without any additional tools (and without running tests), by using the old `build.ps1` bootstrap script. You'll need to pass a version number in, and if you have [Pester](https://github.com/Pester/Pester) and [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer), you can run the 'test.ps1' script to run the tests.

```powershell
./build.ps1 -Semver 5.0.0-prerelease | Split-Path | Import-Module -Force
./test.ps1
```

If you want to test against a different version, you can import it manually and `Invoke-Pester` yourself.

##### You have a lot of other options here ...

You could import the module explicitly from the output path:

```powershell
./build.ps1 | Split-Path | Import-Module -Force
```

You could build into your personal Modules directory, instead:

```powershell
./build -Output ($Profile | Split-Path | Join-Path -ChildPath Modules)
```
### What's in the module, so far:

#### `Build-Module`

Builds a script module from a source project containing one file per function in `Public` and `Private` folders.
Expand Down
12 changes: 7 additions & 5 deletions RequiredModules.psd1
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# NOTE: follow nuget syntax for versions: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
@{
"Configuration" = "[1.3.1,2.0)"
"ModuleBuilder" = "1.*"
"Pester" = "[4.10.1,5.0)"
"PowerShellGet" = "2.0.4"
"PSScriptAnalyzer" = "1.*"
Configuration = "[1.5.0, 2.0)"
Metadata = "[1.5.1, 2.0)"
Pester = "[4.10.1,5.0)"
ModuleBuilder = "[3.0.0, 4.0)"
PSScriptAnalyzer = "[1.21.0,2.0)"
PowerShellGet = "2.0.4"
InvokeBuild = "[5.10.4,6.0)"
}
4 changes: 4 additions & 0 deletions ScriptAnalyzerSettings.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@{
Severity = @('Error', 'Warning')
ExcludeRules = @('PSAvoidGlobalVars', 'PSAvoidUsingDeprecatedManifestFields', 'PSPossibleIncorrectUsageOfAssignmentOperator', 'PSUseShouldProcessForStateChangingFunctions')
}
Loading

0 comments on commit f7dffc8

Please sign in to comment.