Files
stacks-puppet-node/docs/ci-release.md
2023-12-01 12:01:29 -08:00

11 KiB

Releases

All releases are built via a Github Actions workflow named CI (ci.yml), and is responsible for:

  • Verifying code is formatted correctly
  • Building binary archives and checksums
  • Docker images
  • Triggering tests conditionally (different tests run for a release vs a PR)
  1. Releases are only created if a tag is manually provided when the CI workflow is triggered.
  2. Caching is used to speed up testing - a cache is created based on the type of data (i.e. cargo) and the commit sha. tests can be retried quickly since the cache will persist until the cleanup job is run.
  3. nextest is used to run the tests from an archived file that is cached (using commit sha as a key))
    • Two archives are created, one for genesis tests and one for generic tests (it is done this way to reduce the time spent building)
    • Unit-tests are partitioned and multi-threaded to speed up execution time

TL;DR

  • Pushing a feature branch will not trigger a workflow
  • An open/re-opened/synchronized PR will produce a single image built from source on Debian with glibc with 2 tags:
    • stacks-core:<branch-name>
    • stacks-core:<pr-number>
  • A merged PR into default-branch from develop will produce a single image built from source on Debian with glibc:
    • stacks-core:<default-branch-name>
  • An untagged build of any branch will produce a single image built from source on Debian with glibc:
    • stacks-core:<branch-name>
  • A tagged release on a non-default branch will produces:
    • Docker Alpine image for several architectures tagged with:
      • stacks-core:<x.x.x.x.x>
    • Docker Debian image for several architectures tagged with:
      • stacks-core:<x.x.x.x.x-debian>
  • A tagged release on the default branch will produce:
    • Github Release of the specified tag with:
      • Binary archives for several architectures
    • Docker Alpine image for several architectures tagged with:
      • stacks-core:<x.x.x.x.x>
      • stacks-core:<latest>
    • Docker Debian image for several architectures tagged with:
      • stacks-core:<x.x.x.x.x-debian>
      • stacks-core:<latest-debian>

Release workflow

  1. Create a feature branch: feat/fix-something
  2. PR feat/fix-something to the develop branch where the PR is numbered 112
    1. Docker image tagged with the branch name and PR number
    • ex:
      • stacks-core:feat-fix-something
      • stacks-core:pr-112
    1. CI tests are run
  3. PR develop to the default branch where the PR is numbered 112
    1. Docker image tagged with the branch name and PR number
    • ex:
      • stacks-core:feat-fix-something
      • stacks-core:pr-112
    1. CI tests are run
  4. Merge develop branch to the default branch
    1. Docker image is tagged with the default branch master
    • ex:
      • stacks-core:master
    1. CI tests are run
  5. CI workflow is manually triggered on non-default branch with a version, i.e. 2.1.0.0.0-rc0
    1. No Docker images/binaries are created
    2. All release tests are run
  6. CI workflow is manually triggered on default branch with a version, i.e. 2.1.0.0.0
    1. Github release for the manually input version is created with binaries
    2. All release tests are run
    3. Docker image pushed with tags of the input version and latest
    • ex:
    • stacks-core:2.1.0.0.0-debian
    • stacks-core:latest-debian
    • stacks-core:2.1.0.0.0
    • stacks-core:latest

Tests

Tests are separated into several different workflows, with the intention that they can be conditionally run depending upon the triggering operation. For example, on a PR synchronize we don't want to run some identified "slow" tests, but we do want to run the Stacks Blockchain Tests and Bitcoin Tests.

There are also 2 different methods in use with regard to running tests:

  1. Github Actions matrix
  2. nextest partitioning

A matrix is used when there are several known tests that need to be run. Partitions (shards) are used when there is a large and unknown number of tests to run (ex: cargo test to run all tests).

There is also a workflow designed to run tests that are manually triggered: Standalone Tests. This workflow requires you to select which test(s) you want to run, which then triggers a reusbale workflow via conditional. For example, selecting "Epoch Tests" will run the tests defined in Epoch Tests. Likewise, selecting Release Tests will run the same tests as a release workflow.

Files:

Adding/changing tests

With the exception of unit-tests in Stacks Blockchain Tests, adding/removing a test requires a change to the workflow matrix. Example from Atlas Tests:

atlas-tests:
  name: Atlas Test
  runs-on: ubuntu-latest
  strategy:
    ## Continue with the test matrix even if we've had a failure
    fail-fast: false
    ## Run a maximum of 2 concurrent tests from the test matrix
    max-parallel: 2
    matrix:
      test-name:
        - tests::neon_integrations::atlas_integration_test
        - tests::neon_integrations::atlas_stress_integration_test

Example of adding a new test tests::neon_integrations::atlas_new_test:

    ...
    matrix:
      test-name:
        - tests::neon_integrations::atlas_integration_test
        - tests::neon_integrations::atlas_stress_integration_test
        - tests::neon_integrations::atlas_new_test

The separation of tests (outside of Slow Tests) is performed by creating a separate workflow for each type of test that is being run. Using the example above, to add/remove any tests from being run - the matrix will need to be adjusted.

ex:

  • Atlas Tests: Tests related to Atlas
  • Bitcoin Tests: Tests relating to burnchain operations
  • Epoch Tests: Tests related to epoch changes
  • Slow Tests: These tests have been identified as taking longer than others. The threshold used is if a test takes longer than 10 minutes to complete successfully (or times out semi-regularly), it should be added here.
  • Stacks Blockchain Tests:
    • full-genesis: Tests related to full genesis

Triggering a workflow

PR a branch to develop

ex: Branch is named feat/fix-something and the PR is numbered 112


Merging a branch to develop

Nothing is triggered automatically


PR develop to master branches

ex: Branch is named develop and the PR is numbered 113


Merging a PR from develop to master


Manually triggering workflow without tag (any branch)


Manually triggering workflow with tag on a non-default branch (i.e. tag of 2.1.0.0.0-rc0)


Manually triggering workflow with tag on default branch (i.e. tag of 2.1.0.0.0)