mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-04 10:42:23 +00:00
- git-cliff did not work properly with the style of our commit messages, and the CHANGELOG.md it wrote did not fit our style
227 lines
11 KiB
PHP
227 lines
11 KiB
PHP
<?php
|
|
|
|
it('publishes main builds under rolling and commit sha tags with a traceable internal version', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-main-build.yml');
|
|
$dockerfile = file_get_contents(dirname(__DIR__, 2).'/docker/production/Dockerfile');
|
|
$constants = file_get_contents(dirname(__DIR__, 2).'/config/constants.php');
|
|
$versions = json_decode(file_get_contents(dirname(__DIR__, 2).'/versions.json'), true, flags: JSON_THROW_ON_ERROR);
|
|
$nightlyVersions = json_decode(file_get_contents(dirname(__DIR__, 2).'/other/nightly/versions.json'), true, flags: JSON_THROW_ON_ERROR);
|
|
|
|
expect($workflow)
|
|
->toContain('name: Build Coolify Main')
|
|
->toContain('branches: ["main"]')
|
|
->not->toContain('v4.x')
|
|
->toContain('group: coolify-main-build')
|
|
->toContain('cancel-in-progress: false')
|
|
->toContain('IMAGE_NAME }}:main-${{ matrix.arch }}')
|
|
->toContain('--tag "${IMAGE}:main"')
|
|
->toContain('short_sha=${GITHUB_SHA::7}')
|
|
->toContain('SHA: ${{ needs.build-push.outputs.short_sha }}')
|
|
->toContain('--tag "${IMAGE}:sha-${SHA}"')
|
|
->not->toContain('sha-${{ steps.version.outputs.short_sha }}-${{ matrix.arch }}')
|
|
->toContain('org.opencontainers.image.revision=${{ github.sha }}')
|
|
->toContain('php bootstrap/getVersion.php')
|
|
->toContain('version=${BASE_VERSION}-dev.${GITHUB_SHA::9}')
|
|
->toContain('COOLIFY_VERSION=${{ steps.version.outputs.version }}')
|
|
->toContain('sarisia/actions-status-discord@v1')
|
|
->toContain('webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}')
|
|
->not->toContain('IMAGE_NAME }}:latest')
|
|
->and($dockerfile)
|
|
->toContain('ARG COOLIFY_VERSION')
|
|
->toContain('ENV COOLIFY_VERSION=${COOLIFY_VERSION}')
|
|
->and($constants)
|
|
->toContain("'version' => env('COOLIFY_VERSION') ?: '{$versions['coolify']['v4']['version']}'")
|
|
->and($versions['coolify']['nightly']['version'])->toMatch('/^\d+\.\d+-rc\.\d+$/')
|
|
->and(version_compare($versions['coolify']['v4']['version'], $versions['coolify']['nightly']['version'], '<'))->toBeTrue()
|
|
->and($nightlyVersions)->toBe($versions);
|
|
});
|
|
|
|
it('orders a maintenance development build before its stable release', function () {
|
|
expect(version_compare('4.3.2-dev.d64cbda3e', '4.3.2', '<'))->toBeTrue()
|
|
->and(version_compare('4.3.2', '4.3.2-dev.d64cbda3e', '>'))->toBeTrue();
|
|
});
|
|
|
|
it('orders rolling and exact release candidates before the stable release', function () {
|
|
expect(version_compare('4.4-rc.1.d64cbda', '4.4-rc.1', '<'))->toBeTrue()
|
|
->and(version_compare('4.4-rc.1', '4.4-rc.2', '<'))->toBeTrue()
|
|
->and(version_compare('4.4-rc.2', '4.4.0', '<'))->toBeTrue();
|
|
});
|
|
|
|
it('requires a reviewed draft release before building a stable version', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-release.yml');
|
|
|
|
expect($workflow)
|
|
->toContain('name: Release Coolify Stable')
|
|
->toContain('run-name: ${{ inputs.tag }}')
|
|
->toContain('workflow_dispatch:')
|
|
->toContain('tag:')
|
|
->toContain("github.ref_name != 'main'")
|
|
->toContain('github.paginate(github.rest.repos.listReleases')
|
|
->toContain('release.draft')
|
|
->toContain('release.prerelease')
|
|
->toContain('release.body?.trim()')
|
|
->toContain('bootstrap/getVersion.php')
|
|
->toContain('target_commitish: context.sha')
|
|
->toContain('tag_name: process.env.TAG_NAME')
|
|
->toContain('actions/github-script@v8')
|
|
->not->toContain('actions/github-script@v7')
|
|
->not->toContain('environment: production-release')
|
|
->not->toContain('generate-notes');
|
|
});
|
|
|
|
it('runs support image workflows from main', function (string $workflowFile) {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2)."/.github/workflows/{$workflowFile}");
|
|
|
|
expect($workflow)
|
|
->toContain('branches: [ "main" ]')
|
|
->not->toContain('v4.x');
|
|
})->with([
|
|
'helper' => 'coolify-helper.yml',
|
|
]);
|
|
|
|
it('prevents the stable helper workflow from publishing an existing version', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-helper.yml');
|
|
|
|
expect($workflow)
|
|
->toContain('workflow_dispatch:')
|
|
->toContain('check-version:')
|
|
->toContain('needs: check-version')
|
|
->toContain('VERSION="${BASE_VERSION}"')
|
|
->toContain('docker buildx imagetools inspect "$IMAGE"')
|
|
->toContain('Version $VERSION already exists in $registry')
|
|
->toContain('Version $VERSION is available in both registries')
|
|
->toContain('Could not verify $IMAGE')
|
|
->toContain('cancel-in-progress: false');
|
|
});
|
|
|
|
it('publishes the testing host only to Docker Hub', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-testing-host.yml');
|
|
$cleanupWorkflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/cleanup-ghcr-untagged.yml');
|
|
$windowsCompose = file_get_contents(dirname(__DIR__, 2).'/docker-compose.windows.yml');
|
|
$developmentCompose = file_get_contents(dirname(__DIR__, 2).'/docker-compose.dev.yml');
|
|
|
|
expect($workflow)
|
|
->toContain('DOCKER_REGISTRY: docker.io')
|
|
->toContain('IMAGE_NAME: "coollabsio/coolify-testing-host"')
|
|
->toContain('docker/testing-host/Dockerfile')
|
|
->not->toContain('ghcr.io')
|
|
->not->toContain('GITHUB_REGISTRY')
|
|
->and($cleanupWorkflow)->not->toContain('coolify-testing-host')
|
|
->and($windowsCompose)->toContain('docker.io/coollabsio/coolify-testing-host:latest')
|
|
->and($developmentCompose)->toContain('image: coolify-testing-host:dev')
|
|
->toContain('dockerfile: ./docker/testing-host/Dockerfile');
|
|
});
|
|
|
|
it('publishes traceable rolling builds from next without creating an exact rc tag', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-next-build.yml');
|
|
|
|
expect($workflow)
|
|
->toContain('name: Build Coolify Next')
|
|
->toContain('branches: [next]')
|
|
->toContain('group: coolify-next-build')
|
|
->toContain("jq -r '.coolify.nightly.version' versions.json")
|
|
->toContain('VERSION="${RC_VERSION}.${SHORT_SHA}"')
|
|
->toContain('COOLIFY_VERSION=${{ needs.prepare.outputs.version }}')
|
|
->toContain('--tag "${IMAGE}:sha-${SHA}"')
|
|
->toContain('--tag "${IMAGE}:${VERSION}"')
|
|
->toContain('--tag "${IMAGE}:next"')
|
|
->toContain('sarisia/actions-status-discord@v1')
|
|
->toContain('webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}')
|
|
->not->toContain('--tag "${IMAGE}:${RC_VERSION}"')
|
|
->not->toContain('--tag "${IMAGE}:latest"');
|
|
});
|
|
|
|
it('requires a reviewed draft prerelease before publishing an exact rc', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-rc-release.yml');
|
|
|
|
expect($workflow)
|
|
->toContain('name: Release Coolify RC')
|
|
->toContain('run-name: ${{ inputs.tag }}')
|
|
->toContain("github.ref != 'refs/heads/next'")
|
|
->toContain('group: coolify-rc-release')
|
|
->toContain('^v[0-9]+\\.[0-9]+-rc\\.[0-9]+$')
|
|
->toContain("jq -r '.coolify.nightly.version' versions.json")
|
|
->toContain('release.draft')
|
|
->toContain('!release.prerelease')
|
|
->toContain('release.body?.trim()')
|
|
->toContain('revalidate:')
|
|
->toMatch('/revalidate:.*?permissions:\s+contents: write/s')
|
|
->toContain('needs: [validate, build, revalidate]')
|
|
->toContain('COOLIFY_VERSION=${{ needs.validate.outputs.version }}')
|
|
->toContain('--tag "${IMAGE}:${VERSION}"')
|
|
->toContain('--tag "${IMAGE}:next"')
|
|
->toContain('prerelease: true')
|
|
->toContain('actions/github-script@v8')
|
|
->not->toContain('--tag "${IMAGE}:latest"')
|
|
->not->toContain('environment:');
|
|
});
|
|
|
|
it('rebuilds stable images and publishes the reviewed draft after both architectures succeed', function () {
|
|
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-release.yml');
|
|
|
|
expect($workflow)
|
|
->toContain('docker/build-push-action@v6')
|
|
->toContain('COOLIFY_VERSION=${{ needs.validate.outputs.version }}')
|
|
->toContain('release-${{ needs.validate.outputs.version }}-${{ github.sha }}-${{ matrix.arch }}')
|
|
->toContain('--tag "${IMAGE}:${VERSION}"')
|
|
->toContain('--tag "${IMAGE}:latest"')
|
|
->toContain('github.rest.repos.getRelease')
|
|
->toContain('release.target_commitish !== context.sha')
|
|
->toContain('release_id: Number(process.env.RELEASE_ID)')
|
|
->toContain('draft: false')
|
|
->toContain('permissions: {}')
|
|
->not->toContain('sarisia/actions-status-discord@v1')
|
|
->not->toContain('SOURCE_TAG="sha-${RELEASE_SHA}"');
|
|
});
|
|
|
|
it('documents the production, rc, and hotfix release flows', function () {
|
|
$releaseGuide = file_get_contents(dirname(__DIR__, 2).'/RELEASE.md');
|
|
|
|
expect($releaseGuide)
|
|
->toContain('| `main` | Latest production source |')
|
|
->toContain('| `next` | Feature integration and RC releases |')
|
|
->toContain('| `hotfix/X.Y.Z` | Production fixes based on `main` |')
|
|
->toContain('feature/* → next → RC')
|
|
->toContain('next → main → stable release')
|
|
->toContain('main → hotfix/X.Y.Z → main → next')
|
|
->toContain('reviewed draft GitHub Release')
|
|
->toContain('workflows never edit or commit versions')
|
|
->toContain('Update the CDN only after the release is approved')
|
|
->not->toContain('`edge`')
|
|
->not->toContain('promotes the existing SHA image');
|
|
});
|
|
|
|
it('documents pull request targets for fixes and features', function () {
|
|
$contributingGuide = file_get_contents(dirname(__DIR__, 2).'/CONTRIBUTING.md');
|
|
|
|
expect($contributingGuide)
|
|
->toContain('Fixes and small improvements')
|
|
->toContain('target `main`')
|
|
->toContain('New features and larger changes')
|
|
->toContain('target `next`')
|
|
->toContain('branch from `main`')
|
|
->toContain('branch from `next`')
|
|
->not->toContain('All pull requests must target the `next` branch');
|
|
});
|
|
|
|
it('guides issue authors to the correct contribution branch', function () {
|
|
$bugReport = file_get_contents(dirname(__DIR__, 2).'/.github/ISSUE_TEMPLATE/01_BUG_REPORT.yml');
|
|
$issueConfig = file_get_contents(dirname(__DIR__, 2).'/.github/ISSUE_TEMPLATE/config.yml');
|
|
|
|
expect($bugReport)
|
|
->toContain('branch from `main` and target `main`')
|
|
->and($issueConfig)
|
|
->toContain('Feature code should branch from `next` and target `next`')
|
|
->toContain('Small fixes should target `main`; larger changes should target `next`');
|
|
});
|
|
|
|
it('ships versions.json in the production image so version checks work right after an upgrade', function () {
|
|
$dockerfile = file_get_contents(dirname(__DIR__, 2).'/docker/production/Dockerfile');
|
|
$dockerignore = file_get_contents(dirname(__DIR__, 2).'/.dockerignore');
|
|
|
|
expect($dockerfile)
|
|
->toContain('COPY --chown=www-data:www-data versions.json ./versions.json')
|
|
->and($dockerignore)
|
|
->not->toMatch('/^\/?versions\.json$/m');
|
|
});
|