Skip to content

Framework for testing Smalltalk projects with GitHub Actions, GitLab CI, Travis CI, AppVeyor, and others.

License

Notifications You must be signed in to change notification settings

hpi-swa/smalltalkCI

Repository files navigation

smalltalkCI

GitHub Workflow Status Coverage Status

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.

ESUG 13th Innovation Technology Awards

Table Of Contents

Features

  1. Export your project in a compatible format (e.g., Tonel or FileTree).
  2. Enable a CI service for your repository (e.g., GitHub Actions).
  3. 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.
  4. Create a .smalltalk.ston file and specify how to load and test your project.
  5. 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

Templates

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 ]
    }
  ]
}

GitHub Action Templates

For GitHub Action templates, please refer to the Marketplace listing of the setup-smalltalkCI action.

GitLab CI Template

.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 CI Templates

.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
    }
  ],
  ...
}

Resulting build matrix

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

Resulting build matrix

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 Templates

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"'

Resulting build matrix

Smalltalk Config
Squeak32-5.1 .smalltalk.ston
Squeak64-trunk .bleedingEdge.ston
Pharo32-6.0 .smalltalk.ston
Pharo64-alpha .bleedingEdge.ston

Further Configuration

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).

SCIMetacelloLoadSpec

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
}
SCIMonticelloLoadSpec

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
}
SCIGoferLoadSpec

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
}

TestCase Selection

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)
  }
}

Coverage Testing

See COVERAGE.md.

Custom Scripts

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 SCICustomScripts 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 ]
    }
  ]
}

Command Line Options

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

Collection Of Anonymous Build Metrics

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.

Travis-specific Options

Travis Timeouts

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.

Using A Different smalltalkCI Branch Or Fork

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

Contributing

Please feel free to open issues or to send pull requests if you'd like to discuss an idea or a problem.

Projects Using smalltalkCI

In alphabetical order:

Feel free to send a PR to add your Smalltalk project to the list. Please add [ci skip] to your commit message.