Validation CI #6273
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Validation CI | |
on: | |
pull_request: | |
push: | |
branches: [ master ] | |
release: | |
types: [ published ] | |
schedule: | |
# run every day at 0252, 0852, 1452, and 2052 UTC | |
- cron: '52 1,7,13,19 * * *' | |
workflow_dispatch: | |
env: | |
TERM: xterm | |
jobs: | |
changes: | |
name: Check for file changes | |
runs-on: ubuntu-latest | |
permissions: | |
pull-requests: read | |
outputs: | |
ci: ${{ steps.filter.outputs.ci }} | |
dependencies: ${{ steps.filter.outputs.dependencies }} | |
docker: ${{ steps.filter.outputs.docker }} | |
docker-files: ${{ steps.filter.outputs.docker_files }} | |
markdown: ${{ steps.filter.outputs.markdown }} | |
helpers: ${{ steps.filter.outputs.helpers }} | |
shell: ${{ steps.filter.outputs.shell }} | |
spelling: ${{ steps.filter.outputs.spelling }} | |
test: ${{ steps.filter.outputs.test }} | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: dorny/paths-filter@v3 | |
id: filter | |
with: | |
filters: resources/config/paths-filter.yaml | |
list-files: 'shell' | |
dependencies-check: | |
name: Check depencencies | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
pull-requests: write | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Renovate | |
uses: renovatebot/[email protected] | |
with: | |
configurationFile: 'resources/config/renovate-config.json' | |
token: ${{ secrets.RENOVATE_TOKEN }} | |
- name: Dependency Review | |
uses: actions/dependency-review-action@v4 | |
with: | |
config-file: 'resources/config/dependency-review.yaml' | |
base-ref: ${{ github.event.pull_request.base.sha || 'master' }} | |
head-ref: ${{ github.event.pull_request.head.sha || github.ref }} | |
shell-lint: | |
name: Lint the shell code | |
needs: changes | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.docker == 'true' || | |
needs.changes.outputs.helpers == 'true' || | |
needs.changes.outputs.shell == 'true' || | |
needs.changes.outputs.test == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Lint with shellcheck and shfmt | |
uses: luizm/[email protected] | |
env: | |
SHELLCHECK_OPTS: >- | |
--enable add-default-case | |
--enable avoid-nullary-conditions | |
--enable check-unassigned-uppercase | |
--enable deprecate-which | |
--enable quote-safe-variables | |
--enable require-variable-braces | |
SHFMT_OPTS: >- | |
--case-indent | |
--func-next-line | |
--indent 2 | |
--space-redirects | |
yaml-lint: | |
name: Lint the yaml code | |
needs: changes | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.docker == 'true' || | |
needs.changes.outputs.shell == 'true' || | |
needs.changes.outputs.test == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Lint workflow files | |
run: | | |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) | |
./actionlint -color -verbose | |
shell: bash | |
dockerfile-lint: | |
name: Lint the Dockerfile code | |
needs: changes | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.docker == 'true' || | |
needs.changes.outputs.shell == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Lint Dockerfiles | |
uses: luke142367/[email protected] | |
with: | |
target: docker/Dockerfile* | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
markdown-checks: | |
name: Check the documentation | |
needs: changes | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.markdown == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Lint the markdown | |
uses: avto-dev/markdown-lint@v1 | |
with: | |
config: 'resources/config/markdownlint.yaml' | |
args: '*/*.md' | |
ignore: './docs/pull_request_template.md' | |
- name: Check spelling | |
uses: rojopolis/spellcheck-github-actions@v0 | |
with: | |
config_path: 'resources/config/spellcheck.yaml' | |
output_file: 'spellcheck-output.txt' | |
- uses: actions/upload-artifact@v4 | |
if: '!cancelled()' | |
with: | |
name: Spellcheck Output | |
path: spellcheck-output.txt | |
markdown-links: | |
name: Check hyperlinks | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Run linkspector on markdown | |
uses: umbrelladocs/action-linkspector@v1 | |
with: | |
config_file: 'resources/config/linkspector.yaml' | |
fail_on_error: true | |
reporter: github-check | |
conventional-commits: | |
name: Check pull request title | |
if: github.event_name == 'pull_request' | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Validate pull request title as a conventional commit | |
run: | | |
PR_TITLE="$(jq --raw-output .pull_request.title "$GITHUB_EVENT_PATH")" | |
PR_REGEX="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9\-]+\))?: .{1,}$" | |
if [[ ${PR_TITLE} =~ ${PR_REGEX} ]]; then | |
echo "Pull request title '${PR_TITLE}' is valid." | |
else | |
echo "Error: Pull request title does not follow Conventional Commits format." | |
echo "Expected format: <type>(<scope>): <description>" | |
echo "Actual title: ${PR_TITLE}" | |
exit 1 | |
fi | |
run-nodebuilder-baremetal: | |
name: Test ${{ matrix.job-purpose }} on ${{ matrix.os-friendly-name }} | |
needs: [changes, shell-lint, yaml-lint] | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.shell == 'true' || | |
needs.changes.outputs.test == 'true' | |
}} | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
max-parallel: 5 | |
matrix: | |
job-purpose: [package, source] | |
os: [ubuntu-22.04, ubuntu-24.04, macos-13, macos-latest, macos-15] | |
exclude: | |
- { job-purpose: source, os: macos-13 } | |
include: | |
- job-purpose: package | |
additional-args: '' | |
- job-purpose: source | |
additional-args: '--compile' | |
- os: ubuntu-22.04 | |
os-friendly-name: Ubuntu 22 | |
check-environment-command: cat /etc/os-release && lscpu && grep Mem /proc/meminfo | |
remove-firefox-command: sudo apt-get remove --assume-yes firefox | |
cache-path: | | |
/var/cache/apt/archives/*.deb | |
/var/lib/apt/lists/*.ubuntu.com_ubuntu_dists_* | |
/var/lib/apt/lists/download.docker.com_linux_ubuntu_dists_* | |
/var/lib/apt/lists/dl.google.com_linux_chrome_deb_dists_* | |
/var/lib/apt/lists/packages.microsoft.com_repos_code_dists_* | |
/var/lib/apt/lists/pkg.cloudflareclient.com_dists_* | |
path-to-bitcoin-log: '/home/runner/.bitcoin/debug.log' | |
- os: ubuntu-24.04 | |
os-friendly-name: Ubuntu 24 | |
check-environment-command: cat /etc/os-release && lscpu && grep Mem /proc/meminfo | |
remove-firefox-command: sudo apt-get remove --assume-yes firefox | |
path-to-bitcoin-log: '/home/runner/.bitcoin/debug.log' | |
- os: macos-13 | |
os-friendly-name: macOS 13 | |
check-environment-command: sw_vers && sysctl machdep.cpu.core_count machdep.cpu.thread_count machdep.cpu.brand_string && memory_pressure -Q | |
path-to-bitcoin-log: '/Users/runner/Library/Application Support/Bitcoin/debug.log' | |
- os: macos-latest | |
os-friendly-name: macOS 14 | |
check-environment-command: sw_vers && sysctl machdep.cpu.core_count machdep.cpu.thread_count machdep.cpu.brand_string && memory_pressure -Q | |
path-to-bitcoin-log: '/Users/runner/Library/Application Support/Bitcoin/debug.log' | |
- os: macos-15 | |
os-friendly-name: macOS 15 | |
check-environment-command: sw_vers && sysctl machdep.cpu.core_count machdep.cpu.thread_count machdep.cpu.brand_string && memory_pressure -Q | |
path-to-bitcoin-log: '/Users/runner/Library/Application Support/Bitcoin/debug.log' | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Check the current environment | |
run: | | |
uname -a | |
${{ matrix.check-environment-command }} | |
df -h | |
date -u | |
- name: Change owner of apt archives | |
if: contains(matrix.os, 'ubuntu') | |
run: sudo chown -R "$(whoami)" /var/cache/apt/archives | |
- name: Cache system archives | |
if: matrix.cache-path != null | |
uses: actions/cache@v4 | |
with: | |
path: ${{ matrix.cache-path }} | |
key: cache-updates-${{ matrix.os }}-${{ github.run_id }} | |
restore-keys: cache-updates-${{ matrix.os }} | |
- name: Remove the snap package | |
if: matrix.remove-firefox-command != null | |
run: ${{ matrix.remove-firefox-command }} | |
- name: Test the console output ${{ matrix.additional-args }} | |
id: test-nodebuilder | |
run: /bin/sh -x ./test/test_nodebuilder --ref "${GITHUB_SHA}" ${{ matrix.additional-args }} | |
timeout-minutes: 120 | |
continue-on-error: true | |
- name: If test failed, debug nodebuilder ${{ matrix.additional-args }} | |
if: steps.test-nodebuilder.outcome == 'failure' | |
run: | | |
CI_NODEBUILDER_URL="https://github.com/bitcoin-tools/nodebuilder/raw/${GITHUB_SHA}/nodebuilder" | |
CI_NODEBUILDER_SCRIPT="$(basename "${CI_NODEBUILDER_URL}")" | |
[ -n "$(ls /usr/local/bin/*bitcoin* 2> /dev/null)" ] && | |
rm /usr/local/bin/*bitcoin* | |
wget --no-verbose --retry-connrefused "${CI_NODEBUILDER_URL}" && | |
chmod u+x "${CI_NODEBUILDER_SCRIPT}" | |
sh -x "./${CI_NODEBUILDER_SCRIPT}" ${{ matrix.additional-args }} | |
timeout-minutes: 120 | |
- name: Save Bitcoin Core log as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ matrix.os }}-${{ matrix.job-purpose }}-bitcoin-debug.log | |
path: ${{ matrix.path-to-bitcoin-log }} | |
- name: If test failed, fail the job | |
if: steps.test-nodebuilder.outcome == 'failure' | |
run: printf '%s\n' "Review the step 'Test the console output' above." && exit 1 | |
run-nodebuilder-freebsd: | |
name: Test source on FreeBSD | |
needs: [changes, shell-lint, yaml-lint] | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.shell == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Test the console output | |
uses: vmactions/freebsd-vm@v1 | |
timeout-minutes: 180 | |
with: | |
prepare: | | |
echo "${TERM:-TERM is not found}" | |
uname -a | |
cat /etc/os-release | |
nproc | |
sysctl -a | grep ' memory' | head -2 | |
df -h | |
commmand -v tput | |
tput colors | |
date -u | |
run: | | |
sh -x ./test/test_nodebuilder --ref "${GITHUB_SHA}" | |
[ "$?" -gt 0 ] && echo "test_nodebuilder exited with non-zero status" >&2 && exit 1 | |
[ -f "${HOME}/.bitcoin/debug.log" ] && cp "${HOME}/.bitcoin/debug.log" . | |
- name: Save Bitcoin Core log as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: freebsd-source-bitcoin-debug.log | |
path: /home/runner/work/nodebuilder/nodebuilder/debug.log | |
run-nodebuilder-netbsd: | |
name: Test source on NetBSD | |
needs: [changes, shell-lint, yaml-lint] | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.shell == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Test the console output | |
uses: vmactions/netbsd-vm@v1 | |
timeout-minutes: 180 | |
with: | |
prepare: | | |
echo "${TERM:-TERM is not found}" | |
uname -a | |
sysctl -n hw.ncpu | |
sysctl -n hw.physmem64 | |
swapctl -l | |
df -h | |
date -u | |
run: | | |
sh -x ./nodebuilder | |
[ "$?" -gt 0 ] && echo "test_nodebuilder exited with status $?" >&2 && exit 1 | |
[ -f "/root/.bitcoin/debug.log" ] && cp "/root/.bitcoin/debug.log" . | |
- name: Save Bitcoin Core log as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: netbsd-source-bitcoin-debug.log | |
path: /home/runner/work/nodebuilder/nodebuilder/debug.log | |
run-nodebuilder-openbsd: | |
name: Test source on OpenBSD | |
needs: [changes, shell-lint, yaml-lint] | |
if: >- | |
${{ | |
github.event.action == 'prerelease' || | |
github.event.action == 'published' || | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.shell == 'true' | |
}} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Test the console output | |
uses: vmactions/openbsd-vm@v1 | |
timeout-minutes: 180 | |
with: | |
prepare: | | |
echo "${TERM:-TERM is not found}" | |
uname -a | |
sysctl hw.ncpu | |
sysctl -a | grep 'hw.physmem\|hw.usermem' | |
df -h | |
commmand -v tput | |
tput colors | |
date -u | |
run: | | |
sh -x ./test/test_nodebuilder --ref "${GITHUB_SHA}" | |
[ "$?" -gt 0 ] && echo "test_nodebuilder exited with status $?" >&2 && exit 1 | |
[ -f "/home/bitcoin/.bitcoin/debug.log" ] && cp "/home/bitcoin/.bitcoin/debug.log" . | |
find / -name debug.log 2> /dev/null | grep bitcoin || true | |
- name: Save Bitcoin Core log as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: openbsd-source-bitcoin-debug.log | |
path: /home/runner/work/nodebuilder/nodebuilder/debug.log | |
run-nodebuilder-docker: | |
name: Docker image for ${{ matrix.container }} | |
needs: [changes, dockerfile-lint, shell-lint, yaml-lint] | |
if: >- | |
github.event.action != 'prerelease' && | |
github.event.action != 'published' && | |
( | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
needs.changes.outputs.docker == 'true' || | |
needs.changes.outputs.shell == 'true' | |
) | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
max-parallel: 5 | |
matrix: | |
include: | |
- { container: Gentoo, dockerfile: Dockerfile_gentoo } | |
- { container: Alpine, dockerfile: Dockerfile_alpine } | |
- { container: Amazon Linux, dockerfile: Dockerfile_amazonlinux } | |
- { container: Arch, dockerfile: Dockerfile_archlinux } | |
- { container: Clear Linux, dockerfile: Dockerfile_clearlinux } | |
- { container: Debian, dockerfile: Dockerfile_debian } | |
- { container: Fedora, dockerfile: Dockerfile_fedora } | |
- { container: Kali, dockerfile: Dockerfile_kali } | |
- { container: Manjaro, dockerfile: Dockerfile_manjarolinux } | |
- { container: Oracle Linux, dockerfile: Dockerfile_oraclelinux } | |
- { container: Red Hat Enterprise, dockerfile: Dockerfile_redhat-ubi9 } | |
- { container: Rocky Linux, dockerfile: Dockerfile_rockylinux } | |
- { container: SUSE Enterprise, dockerfile: Dockerfile_sles } | |
- { container: Ubuntu, dockerfile: Dockerfile } | |
- { container: openSUSE Leap, dockerfile: Dockerfile_opensuse-leap } | |
- { container: openSUSE Tumbleweed, dockerfile: Dockerfile_opensuse-tumbleweed } | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Check the current OS version | |
run: grep 'VERSION\|ID' /etc/os-release && uname -a | |
- name: Build the ${{ matrix.container }} docker image | |
if: >- | |
( | |
needs.changes.outputs.ci == 'true' || | |
needs.changes.outputs.dependencies == 'true' || | |
contains(needs.changes.outputs.docker-files, matrix.dockerfile) || | |
needs.changes.outputs.shell == 'true' | |
) | |
&& | |
( | |
matrix.container != 'Gentoo' || | |
contains(needs.changes.outputs.docker-files, 'Dockerfile_gentoo') || | |
( | |
github.event.action == '' && | |
github.event.before == '' && | |
github.event.inputs == null | |
) | |
) | |
uses: docker/build-push-action@v6 | |
timeout-minutes: 300 | |
with: | |
build-args: NODEBUILDER_VERSION=${{ github.sha || github.head_ref || 'master' }} | |
context: . | |
file: docker/${{ matrix.dockerfile }} |