Skip to content

Commit f7dffc8

Browse files
authored
Add new line before the content of each script file (fixes #126)
Merge pull request #127 from johlju/f/issue-126
2 parents d183d88 + 7d9e7da commit f7dffc8

21 files changed

+341
-132
lines changed

.earthlyignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# ignore Modules (because we output there now)
2+
/Modules/*
3+
# These aren't part of the module (yet)
4+
/PotentialContribution/*
5+
/Content/*

.github/workflows/build.yml

Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,62 @@
1-
name: Build on push
2-
on: [push]
1+
name: CI
2+
3+
on:
4+
push: {}
5+
pull_request:
6+
branches: [ main ]
7+
38
jobs:
49
build:
5-
runs-on: windows-latest
10+
runs-on: ubuntu-latest
11+
env:
12+
FORCE_COLOR: 1
613
steps:
7-
- name: Checkout
8-
uses: actions/checkout@v2
9-
- name: GitVersion
10-
id: gitversion
11-
uses: PoshCode/Actions/gitversion@v1
12-
- name: Install-RequiredModules
13-
uses: PoshCode/Actions/install-requiredmodules@v1
14-
- name: Build Module
15-
id: build
16-
uses: PoshCode/actions/build-module@v1
14+
- uses: earthly/actions-setup@v1
1715
with:
18-
path: ${{github.workspace}}/Source
19-
version: ${{ steps.gitversion.outputs.LegacySemVerPadded }}
20-
destination: ${{github.workspace}}/output
21-
- name: Upload Build Output
22-
uses: actions/upload-artifact@v2
16+
github-token: ${{ secrets.GITHUB_TOKEN }}
17+
18+
- uses: actions/checkout@v4
19+
with:
20+
submodules: true
21+
fetch-depth: 0
22+
23+
- name: earthly +test
24+
if: github.ref != 'refs/heads/main'
25+
run: earthly --strict +test
26+
27+
- name: earthly +push
28+
if: github.ref == 'refs/heads/main'
29+
run: earthly --push --secret NUGET_API_KEY --secret PSGALLERY_API_KEY --strict +all
30+
env:
31+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
33+
PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }}
34+
35+
- uses: actions/upload-artifact@v4
36+
with:
37+
name: ModuleBuilder
38+
path: Modules/ModuleBuilder
39+
40+
- uses: actions/upload-artifact@v4
41+
with:
42+
name: TestResults
43+
path: Modules/ModuleBuilder-TestResults
44+
45+
- uses: actions/upload-artifact@v4
2346
with:
24-
name: Modules
25-
path: ${{github.workspace}}/output
47+
name: Packages
48+
path: Modules/ModuleBuilder-Packages
49+
2650
- name: Upload Tests
27-
uses: actions/upload-artifact@v2
51+
uses: actions/upload-artifact@v4
2852
with:
2953
name: PesterTests
3054
path: ${{github.workspace}}/Tests
3155
- name: Upload RequiredModules.psd1
32-
uses: actions/upload-artifact@v2
56+
uses: actions/upload-artifact@v4
3357
with:
3458
name: RequiredModules
3559
path: ${{github.workspace}}/RequiredModules.psd1
36-
- name: Upload PSScriptAnalyzerSettings.psd1
37-
uses: actions/upload-artifact@v2
38-
with:
39-
name: ScriptAnalyzer
40-
path: ${{github.workspace}}/PSScriptAnalyzerSettings.psd1
41-
lint:
42-
needs: build
43-
name: Run PSScriptAnalyzer
44-
runs-on: ubuntu-latest
45-
steps:
46-
- name: Download Build Output
47-
uses: actions/download-artifact@v2
48-
- name: Invoke-ScriptAnalyzer
49-
uses: devblackops/github-action-psscriptanalyzer@master
50-
with:
51-
rootPath: Modules/ModuleBuilder
52-
repoToken: ${{ secrets.GITHUB_TOKEN }}
5360
test:
5461
needs: build
5562
runs-on: ${{ matrix.os }}
@@ -59,7 +66,20 @@ jobs:
5966
os: [windows-latest, ubuntu-latest, macos-latest]
6067
steps:
6168
- name: Download Build Output
62-
uses: actions/download-artifact@v2
69+
uses: actions/download-artifact@v4
70+
with:
71+
name: ModuleBuilder
72+
path: Modules/ModuleBuilder
73+
- name: Download Pester Tests
74+
uses: actions/download-artifact@v4
75+
with:
76+
name: PesterTests
77+
path: PesterTests
78+
- name: Download RequiredModules
79+
uses: actions/download-artifact@v4
80+
with:
81+
name: RequiredModules
82+
6383
- uses: PoshCode/Actions/install-requiredmodules@v1
6484
- uses: PoshCode/Actions/pester@v1
6585
with:

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
# Ignore version number folders and "output" where we build
1+
# All of these folders are (or were) build outputs
22
[0-9]*/
3-
obj/
3+
Modules/
44
Output/
5+
obj/
56
Tools/
67
coverage.xml

.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"powershell.codeFormatting.alignPropertyValuePairs": true,
1212
"powershell.codeFormatting.autoCorrectAliases": true,
1313
"powershell.codeFormatting.useCorrectCasing": true,
14+
"powershell.scriptAnalysis.settingsPath": "ScriptAnalyzerSettings.psd1",
1415
"files.associations": {
15-
"*.ps1xml": "xml"
16+
"*.ps1xml": "xml",
17+
".earthlyignore": "ignore"
1618
}
1719
}

Build.build.ps1

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<#
2+
.SYNOPSIS
3+
./project.build.ps1
4+
.EXAMPLE
5+
Invoke-Build
6+
.NOTES
7+
0.5.0 - Parameterize
8+
Add parameters to this script to control the build
9+
#>
10+
[CmdletBinding()]
11+
param(
12+
# dotnet build configuration parameter (Debug or Release)
13+
[ValidateSet('Debug', 'Release')]
14+
[string]$Configuration = 'Release',
15+
16+
# Add the clean task before the default build
17+
[switch]$Clean,
18+
19+
# Collect code coverage when tests are run
20+
[switch]$CollectCoverage,
21+
22+
# Which projects to build
23+
[Alias("Projects")]
24+
$dotnetProjects = @(),
25+
26+
# Which projects are test projects
27+
[Alias("TestProjects")]
28+
$dotnetTestProjects = @(),
29+
30+
# Further options to pass to dotnet
31+
[Alias("Options")]
32+
$dotnetOptions = @{
33+
"-verbosity" = "minimal"
34+
# "-runtime" = "linux-x64"
35+
}
36+
)
37+
$InformationPreference = "Continue"
38+
$ErrorView = 'DetailedView'
39+
40+
# The name of the module to publish
41+
$script:PSModuleName = "TerminalBlocks"
42+
# Use Env because Earthly can override it
43+
$Env:OUTPUT_ROOT ??= Join-Path $BuildRoot Modules
44+
45+
$Tasks = "Tasks", "../Tasks", "../../Tasks" | Convert-Path -ErrorAction Ignore | Select-Object -First 1
46+
Write-Information "$($PSStyle.Foreground.BrightCyan)Found shared tasks in $Tasks" -Tag "InvokeBuild"
47+
## Self-contained build script - can be invoked directly or via Invoke-Build
48+
if ($MyInvocation.ScriptName -notlike '*Invoke-Build.ps1') {
49+
& "$Tasks/_Bootstrap.ps1"
50+
51+
Invoke-Build -File $MyInvocation.MyCommand.Path @PSBoundParameters -Result Result
52+
53+
if ($Result.Error) {
54+
$Error[-1].ScriptStackTrace | Out-String
55+
exit 1
56+
}
57+
exit 0
58+
}
59+
60+
## The first task defined is the default task. Put the right values for your project type here...
61+
if ($dotnetProjects -and $Clean) {
62+
Add-BuildTask CleanBuild Clean, ($Task ?? "Test")
63+
} elseif ($Clean) {
64+
Add-BuildTask CleanBuild Clean, ($Task ?? "Test")
65+
}
66+
67+
## Initialize the build variables, and import shared tasks, including DotNet tasks
68+
. "$Tasks/_Initialize.ps1"

Earthfile

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
VERSION 0.7
2+
IMPORT github.com/poshcode/tasks
3+
FROM mcr.microsoft.com/dotnet/sdk:7.0
4+
WORKDIR /work
5+
6+
ARG --global EARTHLY_GIT_ORIGIN_URL
7+
ARG --global EARTHLY_BUILD_SHA
8+
ARG --global EARTHLY_GIT_BRANCH
9+
# These are my common paths, used in my shared /Tasks repo
10+
ARG --global OUTPUT_ROOT=/Modules
11+
ARG --global TEST_ROOT=/Tests
12+
ARG --global TEMP_ROOT=/temp
13+
# These are my common build args, used in my shared /Tasks repo
14+
ARG --global MODULE_NAME=ModuleBuilder
15+
ARG --global CONFIGURATION=Release
16+
17+
18+
worker:
19+
# Dotnet tools and scripts installed by PSGet
20+
ENV PATH=$HOME/.dotnet/tools:$HOME/.local/share/powershell/Scripts:$PATH
21+
RUN mkdir /Tasks \
22+
&& git config --global user.email "Jaykul@HuddledMasses.org" \
23+
&& git config --global user.name "Earthly Build"
24+
# I'm using Invoke-Build tasks from this other repo which rarely changes
25+
COPY tasks+tasks/* /Tasks
26+
# Dealing with dependencies first allows docker to cache packages for us
27+
# So the dependency cach only re-builds when you add a new dependency
28+
COPY RequiredModules.psd1 .
29+
# COPY *.csproj .
30+
RUN ["pwsh", "-File", "/Tasks/_Bootstrap.ps1", "-RequiredModulesPath", "RequiredModules.psd1"]
31+
32+
build:
33+
FROM +worker
34+
RUN mkdir $OUTPUT_ROOT $TEST_ROOT $TEMP_ROOT
35+
COPY . .
36+
# make sure you have bin and obj in .earthlyignore, as their content from context might cause problems
37+
RUN ["pwsh", "-Command", "Invoke-Build", "-Task", "Build", "-File", "Build.build.ps1"]
38+
39+
# SAVE ARTIFACT [--keep-ts] [--keep-own] [--if-exists] [--force] <src> [<artifact-dest-path>] [AS LOCAL <local-path>]
40+
SAVE ARTIFACT $OUTPUT_ROOT/$MODULE_NAME AS LOCAL ./Modules/$MODULE_NAME
41+
42+
test:
43+
# If we run a target as a reference in FROM or COPY, it's outputs will not be produced
44+
BUILD +build
45+
FROM +build
46+
# make sure you have bin and obj in .earthlyignore, as their content from context might cause problems
47+
RUN ["pwsh", "-Command", "Invoke-Build", "-Task", "Test", "-File", "Build.build.ps1"]
48+
49+
# SAVE ARTIFACT [--keep-ts] [--keep-own] [--if-exists] [--force] <src> [<artifact-dest-path>] [AS LOCAL <local-path>]
50+
SAVE ARTIFACT $TEST_ROOT AS LOCAL ./Modules/$MODULE_NAME-TestResults
51+
52+
# pack:
53+
# BUILD +test # So that we get the module artifact from build too
54+
# FROM +test
55+
# RUN ["pwsh", "-Command", "Invoke-Build", "-Task", "Pack", "-File", "Build.build.ps1", "-Verbose"]
56+
# SAVE ARTIFACT $OUTPUT_ROOT/publish/*.nupkg AS LOCAL ./Modules/$MODULE_NAME-Packages/
57+
58+
push:
59+
FROM +build
60+
RUN --push --secret NUGET_API_KEY --secret PSGALLERY_API_KEY -- \
61+
pwsh -Command Invoke-Build -Task Push -File Build.build.ps1 -Verbose
62+
63+
all:
64+
# BUILD +build
65+
BUILD +test
66+
BUILD +push

ReadMe.md

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,62 +21,43 @@ This module is the first concrete step in the project (although it currently con
2121

2222
### Building from source
2323

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

26-
#### 1. Get the source, obviously
26+
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.
2727

2828
```powershell
2929
git clone https://github.com/PoshCode/ModuleBuilder.git
3030
cd Modulebuilder
31+
earthly +test
3132
```
3233

33-
#### 2. Install dependencies
34+
#### Building without earthly
3435

35-
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:
36+
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:
3637

3738
```powershell
38-
./Install-RequiredModule.ps1
39+
git clone https://github.com/PoshCode/ModuleBuilder.git
40+
git clone https://github.com/PoshCode/Tasks.git
3941
```
4042

41-
#### 3. Run the `build.ps1` script.
42-
43-
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.
43+
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.
4444

4545
```powershell
46-
./build.ps1
46+
cd Modulebuilder
47+
./Build.build.ps1
4748
```
4849

49-
If you don't have `gitversion` handy, you can just specify a version for the `-Semver` parameter:
50-
51-
```powershell
52-
./build.ps1 -Semver 2.1.0-beta
53-
```
50+
This _should_ work on Windows, Linux, and MacOS, but I only test the process on Windows, and in the Linux containers via earthly.
5451

55-
#### 4. Run tests with Pester
52+
#### The old-fashioned way
5653

57-
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:
54+
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.
5855

5956
```powershell
57+
./build.ps1 -Semver 5.0.0-prerelease | Split-Path | Import-Module -Force
6058
./test.ps1
6159
```
6260

63-
If you want to test against a different version, you can import it manually and `Invoke-Pester` yourself.
64-
65-
##### You have a lot of other options here ...
66-
67-
You could import the module explicitly from the output path:
68-
69-
```powershell
70-
./build.ps1 | Split-Path | Import-Module -Force
71-
```
72-
73-
You could build into your personal Modules directory, instead:
74-
75-
```powershell
76-
./build -Output ($Profile | Split-Path | Join-Path -ChildPath Modules)
77-
```
78-
### What's in the module, so far:
79-
8061
#### `Build-Module`
8162

8263
Builds a script module from a source project containing one file per function in `Public` and `Private` folders.

RequiredModules.psd1

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# NOTE: follow nuget syntax for versions: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
22
@{
3-
"Configuration" = "[1.3.1,2.0)"
4-
"ModuleBuilder" = "1.*"
5-
"Pester" = "[4.10.1,5.0)"
6-
"PowerShellGet" = "2.0.4"
7-
"PSScriptAnalyzer" = "1.*"
3+
Configuration = "[1.5.0, 2.0)"
4+
Metadata = "[1.5.1, 2.0)"
5+
Pester = "[4.10.1,5.0)"
6+
ModuleBuilder = "[3.0.0, 4.0)"
7+
PSScriptAnalyzer = "[1.21.0,2.0)"
8+
PowerShellGet = "2.0.4"
9+
InvokeBuild = "[5.10.4,6.0)"
810
}

ScriptAnalyzerSettings.psd1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@{
2+
Severity = @('Error', 'Warning')
3+
ExcludeRules = @('PSAvoidGlobalVars', 'PSAvoidUsingDeprecatedManifestFields', 'PSPossibleIncorrectUsageOfAssignmentOperator', 'PSUseShouldProcessForStateChangingFunctions')
4+
}

0 commit comments

Comments
 (0)