Community-supported framework for testing Smalltalk projects on Linux, OS X, and Windows with built-in support for GitHub Actions, GitLab CI/CD, Travis CI, and AppVeyor.
It is inspired by builderCI and aims to provide a uniform and easy way to load and test Smalltalk projects.
- Features
- How to set up Continuous Integration for your Smalltalk project
- How to test your Smalltalk project locally
- List of Supported Images
- Templates
- Further Configuration
- Contributing
- Projects using smalltalkCI
- Compatible across different Smalltalk dialects (Squeak, Pharo, GemStone)
- Runs on GitHub Actions, GitLab CI, Travis CI, AppVeyor, and other CI services
- Simple configuration via
.smalltalk.ston
,setup-smalltalkCI
action,.gitlab-ci.yml
,.travis.yml
, andappveyor.yml
- Supports Linux, macOS, and Windows and can be run locally (e.g. for debugging purposes)
- Supports coverage testing
- Exports test results in the JUnit XML format as part of the build log
- Export your project in a compatible format (e.g., Tonel or FileTree).
- Enable a CI service for your repository (e.g., GitHub Actions).
- Create a config file for your CI service (see below for templates) and specify the Smalltalk image(s) you want your project to be tested against.
- Create a
.smalltalk.ston
file and specify how to load and test your project. - Push all of this to your repository and enjoy your fast Smalltalk builds!
You can use smalltalkCI to run your project's tests locally. Just clone or download smalltalkCI and then you can initiate a local build in headful mode like this:
bin/smalltalkci -s <IMAGE> --headful /path/to/your/project/.smalltalk.ston
<IMAGE>
can be one of the supported images. You may also want to
have a look at all supported options.
On Windows, you need to run smalltalkCI from a Bash shell such as Git Bash or Cygwin, MinGW, or MSYS2.
Please note: All builds will be stored in _builds
within smalltalkCI's
directory. You may want to delete single or all builds if you don't need them as
they can take up a lot of space on your drive.
Squeak | Pharo | GemStone | Moose | GToolkit |
---|---|---|---|---|
Squeak64-trunk |
Pharo64-alpha |
GemStone64-3.6.x |
Moose64-trunk |
GToolkit64-release |
Squeak64-6.0 |
Pharo64-stable |
GemStone64-3.5.8 |
Moose64-12 |
|
Squeak64-5.3 |
Pharo64-13 |
GemStone64-3.5.7 |
Moose64-11 |
|
Squeak64-5.2 |
Pharo64-12 |
GemStone64-3.5.6 |
Moose64-10 |
|
Squeak64-5.1 |
Pharo64-11 |
GemStone64-3.5.5 |
Moose64-9.0 |
|
Squeak32-trunk |
Pharo64-10 |
Gemstone64-3.5.4 |
Moose64-8.0 |
|
Squeak32-6.0 |
Pharo64-9.0 |
GemStone64-3.5.3 |
||
Squeak32-5.3 |
Pharo64-8.0 |
|||
Squeak32-5.2 |
Pharo64-7.0 |
|||
Squeak32-5.1 |
Pharo64-6.1 |
|||
Squeak32-5.0 |
Pharo64-6.0 |
|||
Squeak32-4.6 |
Pharo32-alpha |
|||
Squeak32-4.5 |
Pharo32-stable |
|||
Pharo32-12 |
||||
Pharo32-11 |
||||
Pharo32-10 |
||||
Pharo32-9.0 |
||||
Pharo32-8.0 |
||||
Pharo32-7.0 |
||||
Pharo32-6.1 |
||||
Pharo32-6.0 |
||||
Pharo32-5.0 |
||||
Pharo32-4.0 |
||||
Pharo32-3.0 |
The following SmalltalkCISpec
will load BaselineOfMyProject
using
Metacello/FileTree from the ./packages
directory in Squeak, Pharo, and
GemStone. See below how you can
customize your SmalltalkCISpec
.
SmalltalkCISpec {
#loading : [
SCIMetacelloLoadSpec {
#baseline : 'MyProject',
#platforms : [ #squeak, #pharo, #gemstone ]
}
]
}
For GitHub Action templates, please refer to the Marketplace listing of the
setup-smalltalkCI
action.
.gitlab-ci.yml
image: hpiswa/smalltalkci
Squeak64Trunk:
script: smalltalkci -s "Squeak64-trunk"
Squeak325.1:
script: smalltalkci -s "Squeak32-5.1"
Pharo64Alpha:
script: smalltalkci -s "Pharo64-alpha"
Pharo327.0:
script: smalltalkci -s "Pharo32-7.0"
# ...
.travis.yml
language: smalltalk
sudo: false
# Select operating system(s)
os:
- linux
- osx
# Select compatible Smalltalk image(s)
smalltalk:
- Squeak64-trunk
- Squeak64-5.1
- Squeak32-4.6
- Squeak32-4.5
# ...
- Pharo64-alpha
- Pharo64-stable
- Pharo64-7.0
- Pharo64-6.1
# ...
- Pharo32-alpha
- Pharo32-stable
- Pharo32-6.1
# ...
- GemStone64-3.5.3
- GemStone64-3.6.0
- GemStone64-3.6.5
# ...
# Override `script` to customize smalltalkCI invocation, e.g.:
#script:
# - smalltalkci .mysmalltalk1.ston
# - travis_wait smalltalkci .mysmalltalk2.ston
# Uncomment to enable caching (only useful for GemStone builds (3x faster))
#cache:
# directories:
# - $SMALLTALK_CI_CACHE
.travis.yml
with multiple smalltalkCI configurations
The build matrix can be expanded with multiple smalltalkCI configuration files
using the smalltalk_config
key:
language: smalltalk
sudo: false
smalltalk:
- Squeak64-trunk
- Pharo64-alpha
smalltalk_config:
- .smalltalk.ston
- .bleedingEdge.ston
The .bleedingEdge.ston
configuration may look like this:
SmalltalkCISpec {
#loading : [
SCIMetacelloLoadSpec {
...
#load : [ 'CoreWithExtras' ],
#version : #bleedingEdge
}
],
...
}
Smalltalk | Config | OS |
---|---|---|
Squeak64-trunk |
.smalltalk.ston |
Linux |
Squeak64-trunk |
.bleedingEdge.ston |
Linux |
Pharo64-alpha |
.smalltalk.ston |
Linux |
Pharo64-alpha |
.bleedingEdge.ston |
Linux |
.travis.yml
with additional jobs
It is possible to add additional jobs to the build matrix
using the smalltalk_config
key:
language: smalltalk
sudo: false
os: osx
smalltalk:
- Squeak32-5.1
- Pharo32-6.0
matrix:
include:
- smalltalk: Squeak64-trunk
smalltalk_config: .bleedingEdge.ston
- smalltalk: Pharo64-alpha
smalltalk_config: .bleedingEdge.ston
allow_failures: # Allow bleeding edge builds to fail
- smalltalk_config: .bleedingEdge.ston
Smalltalk | Config | OS |
---|---|---|
Squeak32-5.1 |
.smalltalk.ston |
macOS |
Pharo32-6.0 |
.smalltalk.ston |
macOS |
Squeak64-trunk |
.bleedingEdge.ston |
macOS |
Pharo64-alpha |
.bleedingEdge.ston |
macOS |
appveyor.yml
# This is a 64-bit environment, so use 64-bit Cygwin
environment:
CYG_ROOT: C:\cygwin64
CYG_BASH: C:\cygwin64\bin\bash
CYG_CACHE: C:\cygwin64\var\cache\setup
CYG_EXE: C:\cygwin64\setup-x86_64.exe
CYG_MIRROR: http://cygwin.mirror.constant.com
SCI_RUN: /cygdrive/c/smalltalkCI-master/bin/smalltalkci
matrix:
# Currently, only Squeak and Pharo images are supported on AppVeyor.
- SMALLTALK: Squeak64-trunk
- SMALLTALK: Squeak64-5.0
- SMALLTALK: Pharo64-alpha
- SMALLTALK: Pharo64-6.0
# ...
platform:
- x64
install:
- '%CYG_EXE% -dgnqNO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P unzip'
- ps: Start-FileDownload "https://github.com/hpi-swa/smalltalkCI/archive/master.zip" "C:\smalltalkCI.zip"
- 7z x C:\smalltalkCI.zip -oC:\ -y > NULL
build: false
test_script:
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; $SCI_RUN"'
appveyor.yml
with additional jobs
It is possible to add additional jobs to the
build matrix using environment.matrix
as follows:
environment:
CYG_ROOT: C:\cygwin
CYG_BASH: C:\cygwin\bin\bash
CYG_CACHE: C:\cygwin\var\cache\setup
CYG_EXE: C:\cygwin\setup-x86.exe
CYG_MIRROR: http://cygwin.mirror.constant.com
SCI_RUN: /cygdrive/c/SMALLTALKCI-master/bin/smalltalkci
matrix:
- SMALLTALK: Squeak32-5.1
- SMALLTALK: Squeak64-trunk
SMALLTALK_CONFIG: .bleedingEdge.ston
- SMALLTALK: Pharo32-6.0
- SMALLTALK: Pharo64-alpha
SMALLTALK_CONFIG: .bleedingEdge.ston
platform:
- x86
install:
- '%CYG_EXE% -dgnqNO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P unzip'
- ps: Start-FileDownload "https://github.com/hpi-swa/SMALLTALKCI/archive/master.zip" "C:\SMALLTALKCI.zip"
- 7z x C:\SMALLTALKCI.zip -oC:\ -y > NULL
build: false
test_script:
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; $SCI_RUN $SMALLTALK_CONFIG"'
Smalltalk | Config |
---|---|
Squeak32-5.1 |
.smalltalk.ston |
Squeak64-trunk |
.bleedingEdge.ston |
Pharo32-6.0 |
.smalltalk.ston |
Pharo64-alpha |
.bleedingEdge.ston |
smalltalkCI requires a .smalltalk.ston
configuration file which can be
customized for a project to cover various use cases.
The .smalltalk.ston
must be a valid STON file and has to contain a
single SmalltalkCISpec
object.
This object can hold one or more load specifications in
#loading
and configurations for the TestCase selection
in #testing
.
SmalltalkCISpec {
#name : 'My Name', // Name of the SmalltalkCISpec (optional)
#loading : [
// List Of Load Specifications...
],
#testing : {
// TestCase Selection...
}
}
smalltalkCI supports different formats for loading Smalltalk projects and for
each, there is a loading specification.
One or more of those loading specifications have to be provided in the
#loading
list as part of a SmalltalkCISpec
.
smalltalkCI will load all specifications that are compatible with the selected
Smalltalk image (specified via #platforms
).
A SCIMetacelloLoadSpec
loads a project either via the specified Metacello
#baseline
or the Metacello
#configuration
. If a #directory
is specified,
the project will be loaded using FileTree/Metacello
from the given directory.
Otherwise, it will be loaded from the specified #repository
.
SCIMetacelloLoadSpec {
#baseline : 'MyProject', // Define MC Baseline
#configuration : 'MyProject', // Alternatively, define MC Configuration
#directory : 'src', // Path to source-code directory were are packages (i.e. 'packages' or 'src'), in case of packages are not on root
#failOn : [ #OCUndeclaredVariableWarning ], // Fail build on provided list of Warnings
#ignoreImage : true, // If true, Metacello will force a load of a package, overriding a previously existing one
#load : [ 'default' ], // Define MC load attributes
#onConflict : #useIncoming, // When there is a conflict between loaded sources and incoming sources (can be #useIncoming|#useLoaded)
#onUpgrade : #useIncoming, // When loaded sources are an older version than incoming sources (can be #useIncoming|#useLoaded)
#onWarningLog : true, // Log Warning messages to Transcript
#platforms : [ #squeak, #pharo, #gemstone ], // Define compatible platforms
#repository : 'http://smalltalkhub.com/mc/...', // Alternatively, define MC repository
#usernameEnvVar : 'GITHUB_USER', // Environment variable containing the username used for authentication
#passwordEnvVar : 'GITHUB_TOKEN', // Environment variable containing the password used for authentication
#useLatestMetacello : true, // Upgrade Metacello before loading
#version : '1.0.0' // Define MC version (for MC Configurations only)
#registerInIceberg : true // Pharo Only | Register the tested repository in Iceberg
}
A SCIMonticelloLoadSpec
loads a project with Monticello. It is
possible to load the latest version of packages from a remote repository
(#packages
) or specific versions (#versions
).
SCIMonticelloLoadSpec {
#url : 'http://ss3.gemtalksystems.com/ss/...', // Define URL for repository
#packages : ['MyProject-Core', 'MyProject-Tests'], // Load packages and/or
#versions : ['MyProject-Core-aa.12'], // Load specific versions
#usernameEnvVar : 'USERNAME_VAR', // Environment variable containing the username used for authentication
#passwordEnvVar : 'PASSWORD_VAR', // Environment variable containing the password used for authentication
#platforms : [ #squeak, #pharo, #gemstone ] // Define compatible platforms
}
A SCIGoferLoadSpec
works similar to a SCIMonticelloLoadSpec
, but uses
Gofer on top of Monticello to load a project.
SCIGoferLoadSpec {
#url : 'http://smalltalkhub.com/mc/...', // Define URL for repository
#packages : ['MyProject-Core', 'MyProject-Tests'], // Load packages and/or
#versions : ['MyProject-Core-aa.12'], // Load specific versions
#usernameEnvVar : 'USERNAME_VAR', // Environment variable containing the username used for authentication
#passwordEnvVar : 'PASSWORD_VAR', // Environment variable containing the password used for authentication
#platforms : [ #squeak, #pharo, #gemstone ] // Define compatible platforms
}
smalltalkCI runs a list of TestCases during a build.
By default, smalltalkCI will use a list of all TestCases that it has loaded into
the image.
It is possible to adjust this list using the #testing
slot.
In general, TestCases can be selected on class-level (#classes
), on
category-level (#categories
), on package-level (#packages
) and on
project-level (#projects
, GemStone only).
#classes
expects a list of class name symbols, #categories
and #packages
expect category names and prefixes or package names and prefixes respectively.
The default list can be replaced by a list of all TestCases that are present in
the image by setting #allTestCases
to true
.
Additionally, it is possible to add (#include
) or remove (#exclude
) classes
from this list.
The list can also be specified explicitly which means that only these
TestCases will run.
SmalltalkCISpec {
...
#testing : {
// Include specific TestCases
#include : {
#classes : [ #AnotherProjectTestCase ],
#categories : [ 'AnotherProject-Tests' ],
#packages : [ 'AnotherProject.*' ],
#projects : [ 'BaselineOfMyProject' ]
},
// Exclude specific TestCases from testing
#exclude : {
#classes : [ #AnotherProjectTestCase ],
#categories : [ 'AnotherProject-Tests' ],
#packages : [ 'AnotherProject.*' ],
#projects : [ 'ConfigurationOfMyOtherProject' ]
},
#allTestCases : true, // Run all TestCases in image
// Define TestCases explicitly
#classes : [ #MyProjectTestCase ],
#categories : [ 'MyProject-*' ],
#packages : [ 'MyProject.*' ],
#projects : [ 'BaselineOfMyProject' ],
// Other options
#defaultTimeout : 30, // In seconds (Squeak, and Pharo 6 or later)
#failOnSCIDeprecationWarnings : false, // Fail if a deprecated smalltalkCI API is used
#failOnZeroTests : false, // Pass builds that did not run any tests
#hidePassingTests : true, // Hide passing tests when printing to stdout
#serializeError: false // (default: true) Disable serialization of failing test case (e.g. with Fuel in Pharo)
}
}
See COVERAGE.md.
It is possible to run custom scripts before and after the loading and
testing phases (preLoading
, postLoading
, preTesting
, postTesting
).
smalltalkCI can file in single files, lists of files, and
SCICustomScript
s which can be used to only run certain scripts on certain
platforms.
SmalltalkCISpec {
#preLoading : 'scripts/preLoading.st',
#loading : ...,
#postLoading : [
'scripts/postLoading1.st',
'scripts/postLoading2.st'
],
#preTesting : SCICustomScript {
#path : 'scripts/preTesting.st',
#platforms : [ #squeak, #pharo, #gemstone ]
},
#testing : ...,
#postTesting : [
SCICustomScript {
#path : 'scripts/postTestingSqueak.st',
#platforms : [ #squeak ]
},
SCICustomScript {
#path : 'scripts/postTestingPharo.st',
#platforms : [ #pharo ]
}
]
}
smalltalkCI has a couple of command line options that can be useful for debugging purposes or when used locally:
USAGE: bin/smalltalkci [options] /path/to/project/your_smalltalk.ston
This program prepares Smalltalk images/vms, loads projects, and runs tests.
OPTIONS:
--clean Clear cache and delete builds.
-d | --debug Enable debug mode.
-h | --help Show this help text.
--headful Open vm in headful mode and do not close image.
--image Custom image for build (Squeak/Pharo).
--install Install symlink to this smalltalkCI instance.
--print-env Print all environment variables used by smalltalkCI
--no-color Disable colored output
--no-tracking Disable collection of anonymous build metrics (Travis CI & AppVeyor only).
-s | --smalltalk Overwrite Smalltalk image selection.
--uninstall Remove symlink to any smalltalkCI instance.
-v | --verbose Enable 'set -x'.
--vm Custom VM for build (Squeak/Pharo).
EXAMPLE:
bin/smalltalkci -s "Squeak64-trunk" --headful /path/to/project/.smalltalk.ston
smalltalkCI collects anonymous build metrics (Smalltalk dialect, CI environment,
build status, build duration) for public repositories when running on a supported
CI platform. This helps to identify build errors caused by smalltalkCI updates
and therefore helps to improve the service. It is possible to opt-out by using
the --no-tracking
option.
Jobs on Travis CI timeout if they don't produce output for
more than 10 minutes. In the case of long-running tests, it
is possible to increase this timeout by setting $SMALLTALK_CI_TIMEOUT
in your
.travis.yml
to a value greater than 10:
env:
- SMALLTALK_CI_TIMEOUT=30
The above sets the timeout to 30 minutes. Please note that Travis CI enforces a total build timeout of 50 minutes.
By default, the smalltalkCI master branch is used to perform a build. It is
possible to select a different smalltalkCI branch or fork for testing/debugging
purposes by adding the following to the .travis.yml
:
smalltalk_edge:
source: hpi-swa/smalltalkCI
branch: dev
Please feel free to open issues or to send pull requests if you'd like to discuss an idea or a problem.
In alphabetical order:
- @ba-st: Buoy, RenoirSt, Willow.
- @Cormas: Cormas.
- @dalehenrich: obex, tode.
- @DuneSt: Heimdall, MaterialDesignLite, PrismCodeDisplayer.
- @HPI-BP2015H: squeak-parable.
- @hpi-swa: animations, Ohm-S, signals, Sandblocks, Squot, vivide, widgets.
- @hpi-swa-lab: Babylonian Programming/Smalltalk, Squeak by Example, Squeak Inbox Talk.
- @HPI-SWA-Teaching: Algernon-Launcher, AutoTDD, Koans, Morphic Testing Framework, Poppy Print, SpreadSheetTool, TelegramClient, SwaLint.
- @LinqLover: create-image, SimulationStudio, TelegramBot, XmasDecorations.
- @marianopeck: OSSubprocess, FFICHeaderExtractor.
- @Metacello: metacello.
- @newapplesho: aws-sdk-smalltalk, elasticsearch-smalltalk, mixpanel-smalltalk, OpenExchangeRates, pardot-smalltalk, salesforce-smalltalk, sendgrid-smalltalk, twilio-smalltalk.
- @ObjectProfile: Roassal2.
- @OpenPonk: borm-editor, borm-model, class-editor, demo-editor, fsm-editor.
- @OpenSmalltalk: opensmalltalk-vm.
- @pharo-project: pharo-project-proposals.
- @PolyMathOrg: PolyMath.
- @SeasideSt: Grease, Parasol, Seaside.
- @SergeStinckwich: PlayerST.
- @squeak-smalltalk: squeak-app, squeak-filesystem, squeak-ston, squeak-tonel.
- @theseion: Fuel.
- @Uko: GitHubcello, QualityAssistant, Renraku.
- @UMMISCO: Kendrick.
- @zecke: osmo-smsc.
- More Projects...
Feel free to send a PR to add your Smalltalk project to the
list. Please add [ci skip]
to your commit message.