summaryrefslogtreecommitdiffstats
path: root/.github/scripts
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-x.github/scripts/build-artifacts.sh82
-rwxr-xr-x.github/scripts/build-dist.sh71
-rwxr-xr-x.github/scripts/build-static.sh61
-rwxr-xr-x.github/scripts/bump-packaging-version.sh6
-rwxr-xr-x.github/scripts/check-updater.sh49
-rwxr-xr-x.github/scripts/ci-support-pkgs.sh14
-rwxr-xr-x.github/scripts/docker-test.sh60
-rw-r--r--.github/scripts/functions.sh69
-rwxr-xr-x.github/scripts/gen-docker-tags.py14
-rwxr-xr-x.github/scripts/get-static-cache-key.sh15
-rwxr-xr-x.github/scripts/netdata-pkgcloud-cleanup.py190
-rwxr-xr-x.github/scripts/package-upload.sh43
-rwxr-xr-x.github/scripts/package_cloud_wrapper.sh48
-rwxr-xr-x.github/scripts/pkg-test.sh138
-rwxr-xr-x.github/scripts/prepare-release-base.sh176
-rwxr-xr-x.github/scripts/run-updater-check.sh14
-rwxr-xr-x.github/scripts/run_install_with_dist_file.sh39
17 files changed, 1089 insertions, 0 deletions
diff --git a/.github/scripts/build-artifacts.sh b/.github/scripts/build-artifacts.sh
new file mode 100755
index 0000000..569c79a
--- /dev/null
+++ b/.github/scripts/build-artifacts.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+# Builds the netdata-vX.y.Z-xxxx.tar.gz source tarball (dist)
+# and netdata-vX.Y.Z-xxxx.gz.run (static x86_64) artifacts.
+
+set -e
+
+# shellcheck source=.github/scripts/functions.sh
+. "$(dirname "$0")/functions.sh"
+
+NAME="${NAME:-netdata}"
+VERSION="${VERSION:-"$(git describe)"}"
+BASENAME="$NAME-$VERSION"
+
+prepare_build() {
+ progress "Preparing build"
+ (
+ test -d artifacts || mkdir -p artifacts
+ echo "${VERSION}" > packaging/version
+ ) >&2
+}
+
+build_dist() {
+ progress "Building dist"
+ (
+ command -v git > /dev/null && [ -d .git ] && git clean -d -f
+ autoreconf -ivf
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --libexecdir=/usr/libexec \
+ --with-zlib \
+ --with-math \
+ --with-user=netdata \
+ --disable-dependency-tracking \
+ CFLAGS=-O2
+ make dist
+ mv "${BASENAME}.tar.gz" artifacts/
+ ) >&2
+}
+
+build_static_x86_64() {
+ progress "Building static x86_64"
+ (
+ command -v git > /dev/null && [ -d .git ] && git clean -d -f
+ USER="" ./packaging/makeself/build-x86_64-static.sh
+ ) >&2
+}
+
+prepare_assets() {
+ progress "Preparing assets"
+ (
+ cp packaging/version artifacts/latest-version.txt
+
+ cd artifacts || exit 1
+ ln -f "${BASENAME}.tar.gz" netdata-latest.tar.gz
+ ln -f "${BASENAME}.gz.run" netdata-latest.gz.run
+ sha256sum -b ./* > "sha256sums.txt"
+ ) >&2
+}
+
+steps="prepare_build build_dist build_static_x86_64"
+steps="$steps prepare_assets"
+
+_main() {
+ for step in $steps; do
+ if ! run "$step"; then
+ if [ -t 1 ]; then
+ debug
+ else
+ fail "Build failed"
+ fi
+ fi
+ done
+
+ echo "🎉 All Done!"
+}
+
+if [ -n "$0" ] && [ x"$0" != x"-bash" ]; then
+ _main "$@"
+fi
diff --git a/.github/scripts/build-dist.sh b/.github/scripts/build-dist.sh
new file mode 100755
index 0000000..027b621
--- /dev/null
+++ b/.github/scripts/build-dist.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Builds the netdata-vX.y.Z-xxxx.tar.gz source tarball (dist)
+
+set -e
+
+# shellcheck source=.github/scripts/functions.sh
+. "$(dirname "$0")/functions.sh"
+
+NAME="${NAME:-netdata}"
+VERSION="${VERSION:-"$(git describe --always)"}"
+BASENAME="$NAME-$VERSION"
+
+prepare_build() {
+ progress "Preparing build"
+ (
+ test -d artifacts || mkdir -p artifacts
+ echo "${VERSION}" > packaging/version
+ ) >&2
+}
+
+build_dist() {
+ progress "Building dist"
+ (
+ command -v git > /dev/null && [ -d .git ] && git clean -d -f
+ autoreconf -ivf
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --libexecdir=/usr/libexec \
+ --with-zlib \
+ --with-math \
+ --with-user=netdata \
+ --disable-dependency-tracking \
+ CFLAGS=-O2
+ make dist
+ mv "${BASENAME}.tar.gz" artifacts/
+ ) >&2
+}
+
+prepare_assets() {
+ progress "Preparing assets"
+ (
+ cp packaging/version artifacts/latest-version.txt
+ cd artifacts || exit 1
+ ln -f "${BASENAME}.tar.gz" netdata-latest.tar.gz
+ ln -f "${BASENAME}.gz.run" netdata-latest.gz.run
+ sha256sum -b ./* > "sha256sums.txt"
+ ) >&2
+}
+
+steps="prepare_build build_dist prepare_assets"
+
+_main() {
+ for step in $steps; do
+ if ! run "$step"; then
+ if [ -t 1 ]; then
+ debug
+ else
+ fail "Build failed"
+ fi
+ fi
+ done
+
+ echo "🎉 All Done!"
+}
+
+if [ -n "$0" ] && [ x"$0" != x"-bash" ]; then
+ _main "$@"
+fi
diff --git a/.github/scripts/build-static.sh b/.github/scripts/build-static.sh
new file mode 100755
index 0000000..e810514
--- /dev/null
+++ b/.github/scripts/build-static.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# Builds the netdata-vX.Y.Z-xxxx.gz.run (static x86_64) artifact.
+
+set -e
+
+# shellcheck source=.github/scripts/functions.sh
+. "$(dirname "$0")/functions.sh"
+
+BUILDARCH="${1}"
+NAME="${NAME:-netdata}"
+VERSION="${VERSION:-"$(git describe)"}"
+BASENAME="$NAME-$BUILDARCH-$VERSION"
+
+prepare_build() {
+ progress "Preparing build"
+ (
+ test -d artifacts || mkdir -p artifacts
+ ) >&2
+}
+
+build_static() {
+ progress "Building static ${BUILDARCH}"
+ (
+ USER="" ./packaging/makeself/build-static.sh "${BUILDARCH}"
+ ) >&2
+}
+
+prepare_assets() {
+ progress "Preparing assets"
+ (
+ cp packaging/version artifacts/latest-version.txt
+
+ cd artifacts || exit 1
+ ln -s "${BASENAME}.gz.run" "netdata-${BUILDARCH}-latest.gz.run"
+ if [ "${BUILDARCH}" = "x86_64" ]; then
+ ln -s "${BASENAME}.gz.run" netdata-latest.gz.run
+ fi
+ ) >&2
+}
+
+steps="prepare_build build_static"
+steps="$steps prepare_assets"
+
+_main() {
+ for step in $steps; do
+ if ! run "$step"; then
+ if [ -t 1 ]; then
+ debug
+ else
+ fail "Build failed"
+ fi
+ fi
+ done
+
+ echo "🎉 All Done!"
+}
+
+if [ -n "$0" ] && [ x"$0" != x"-bash" ]; then
+ _main "$@"
+fi
diff --git a/.github/scripts/bump-packaging-version.sh b/.github/scripts/bump-packaging-version.sh
new file mode 100755
index 0000000..bffcb0c
--- /dev/null
+++ b/.github/scripts/bump-packaging-version.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+VERSION="$(git describe)"
+echo "$VERSION" > packaging/version
+git add -A
+git ci -m "[netdata nightly] $VERSION"
diff --git a/.github/scripts/check-updater.sh b/.github/scripts/check-updater.sh
new file mode 100755
index 0000000..3df0c9d
--- /dev/null
+++ b/.github/scripts/check-updater.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+set -e
+# shellcheck source=.github/scripts/functions.sh
+. "$(dirname "$0")/functions.sh"
+
+check_successful_update() {
+ progress "Check netdata version after update"
+ (
+ netdata_version=$(netdata -v | awk '{print $2}')
+ updater_version=$(cat packaging/version)
+ if [ "$netdata_version" = "$updater_version" ]; then
+ echo "Update successful!"
+ else
+ exit 1
+ fi
+ ) >&2
+}
+
+check_autoupdate_enabled() {
+ progress "Check autoupdate still enabled after update"
+ (
+ if [ -f /etc/periodic/daily/netdata-updater ] || [ -f /etc/cron.daily/netdata-updater ]; then
+ echo "Update successful!"
+ else
+ exit 1
+ fi
+ ) >&2
+}
+
+steps="check_successful_update check_autoupdate_enabled"
+
+_main() {
+ for step in $steps; do
+ if ! run "$step"; then
+ if [ -t 1 ]; then
+ debug
+ else
+ fail "Build failed"
+ fi
+ fi
+ done
+
+ echo "🎉 All Done!"
+}
+
+if [ -n "$0" ] && [ x"$0" != x"-bash" ]; then
+ _main "$@"
+fi
diff --git a/.github/scripts/ci-support-pkgs.sh b/.github/scripts/ci-support-pkgs.sh
new file mode 100755
index 0000000..bfa9c83
--- /dev/null
+++ b/.github/scripts/ci-support-pkgs.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# This script installs supporting packages needed for CI, which provide following:
+# cron, pidof
+
+set -e
+
+if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/fedora-release ] || [ -f /etc/almalinux-release ]; then
+ # Alma, Fedora, CentOS, Redhat
+ dnf install -y procps-ng cronie cronie-anacron || yum install -y procps-ng cronie cronie-anacron
+elif [ -f /etc/arch-release ]; then
+ # Arch
+ pacman -S --noconfirm cronie
+fi
diff --git a/.github/scripts/docker-test.sh b/.github/scripts/docker-test.sh
new file mode 100755
index 0000000..22821d1
--- /dev/null
+++ b/.github/scripts/docker-test.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+export DEBIAN_FRONTEND=noninteractive
+
+wait_for() {
+ host="${1}"
+ port="${2}"
+ name="${3}"
+ timeout="30"
+
+ if command -v nc > /dev/null ; then
+ netcat="nc"
+ elif command -v netcat > /dev/null ; then
+ netcat="netcat"
+ else
+ printf "Unable to find a usable netcat command.\n"
+ return 1
+ fi
+
+ printf "Waiting for %s on %s:%s ... " "${name}" "${host}" "${port}"
+
+ sleep 30
+
+ i=0
+ while ! ${netcat} -z "${host}" "${port}"; do
+ sleep 1
+ if [ "$i" -gt "$timeout" ]; then
+ printf "Timed out!\n"
+ return 1
+ fi
+ i="$((i + 1))"
+ done
+ printf "OK\n"
+}
+
+if [ -z "$(command -v nc 2>/dev/null)" ] && [ -z "$(command -v netcat 2>/dev/null)" ]; then
+ sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get install -y netcat
+fi
+
+docker run -d --name=netdata \
+ -p 19999:19999 \
+ -v netdataconfig:/etc/netdata \
+ -v netdatalib:/var/lib/netdata \
+ -v netdatacache:/var/cache/netdata \
+ -v /etc/passwd:/host/etc/passwd:ro \
+ -v /etc/group:/host/etc/group:ro \
+ -v /proc:/host/proc:ro \
+ -v /sys:/host/sys:ro \
+ -v /etc/os-release:/host/etc/os-release:ro \
+ --cap-add SYS_PTRACE \
+ --security-opt apparmor=unconfined \
+ netdata/netdata:test
+
+wait_for localhost 19999 netdata || exit 1
+
+curl -sS http://127.0.0.1:19999/api/v1/info > ./response || exit 1
+
+cat ./response
+
+jq '.version' ./response || exit 1
diff --git a/.github/scripts/functions.sh b/.github/scripts/functions.sh
new file mode 100644
index 0000000..7cd2e08
--- /dev/null
+++ b/.github/scripts/functions.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# This file is included by download.sh & build.sh
+
+set -e
+
+color() {
+ fg="$1"
+ bg="${2}"
+ ft="${3:-0}"
+
+ printf "\33[%s;%s;%s" "$ft" "$fg" "$bg"
+}
+
+color_reset() {
+ printf "\033[0m"
+}
+
+ok() {
+ if [ -t 1 ]; then
+ printf "%s[ OK ]%s\n" "$(color 37 42m 1)" "$(color_reset)"
+ else
+ printf "%s\n" "[ OK ]"
+ fi
+}
+
+err() {
+ if [ -t 1 ]; then
+ printf "%s[ ERR ]%s\n" "$(color 37 41m 1)" "$(color_reset)"
+ else
+ printf "%s\n" "[ ERR ]"
+ fi
+}
+
+run() {
+ retval=0
+ logfile="$(mktemp -t "run-XXXXXX")"
+ if "$@" 2> "$logfile"; then
+ ok
+ else
+ retval=$?
+ err
+ tail -n 100 "$logfile" || true
+ fi
+ rm -rf "$logfile"
+ return $retval
+}
+
+progress() {
+ printf "%-40s" "$(printf "%s ... " "$1")"
+}
+
+log() {
+ printf "%s\n" "$1"
+}
+
+error() {
+ log "ERROR: ${1}"
+}
+
+fail() {
+ log "FATAL: ${1}"
+ exit 1
+}
+
+debug() {
+ log "Dropping into a shell for debugging ..."
+ exec /bin/sh
+}
diff --git a/.github/scripts/gen-docker-tags.py b/.github/scripts/gen-docker-tags.py
new file mode 100755
index 0000000..df4dc02
--- /dev/null
+++ b/.github/scripts/gen-docker-tags.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+
+import sys
+
+version = sys.argv[1].split('.')
+suffix = sys.argv[2]
+
+REPO = f'netdata/netdata{suffix}'
+
+MAJOR = ':'.join([REPO, version[0]])
+MINOR = ':'.join([REPO, '.'.join(version[0:2])])
+PATCH = ':'.join([REPO, '.'.join(version[0:3])])
+
+print(','.join([MAJOR, MINOR, PATCH]))
diff --git a/.github/scripts/get-static-cache-key.sh b/.github/scripts/get-static-cache-key.sh
new file mode 100755
index 0000000..d9fa285
--- /dev/null
+++ b/.github/scripts/get-static-cache-key.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+arch="${1}"
+platform="$(packaging/makeself/uname2platform.sh "${arch}")"
+
+docker pull --platform "${platform}" netdata/static-builder
+
+# shellcheck disable=SC2046
+cat $(find packaging/makeself/jobs -type f ! -regex '.*\(netdata\|-makeself\).*') > /tmp/static-cache-key-data
+
+docker run -it --rm --platform "${platform}" netdata/static-builder sh -c 'apk list -I 2>/dev/null' >> /tmp/static-cache-key-data
+
+h="$(sha256sum /tmp/static-cache-key-data | cut -f 1 -d ' ')"
+
+echo "::set-output name=key::static-${arch}-${h}"
diff --git a/.github/scripts/netdata-pkgcloud-cleanup.py b/.github/scripts/netdata-pkgcloud-cleanup.py
new file mode 100755
index 0000000..f6311e4
--- /dev/null
+++ b/.github/scripts/netdata-pkgcloud-cleanup.py
@@ -0,0 +1,190 @@
+#!/bin/env python3
+
+import requests
+from requests.auth import HTTPBasicAuth
+from datetime import date, datetime, timedelta
+import os
+import sys
+import argparse
+from pprint import pprint
+from datetime import datetime
+from dateutil import parser
+
+
+class PackageCloud:
+ NUM_PACKAGE_MINOR_TO_KEEP = 5
+ NUM_RETENTION_DAYS = 30
+ # number of pages to process. Use '0' to process all
+ MAX_PAGES = 0
+
+ def __init__(self, repo_type, dry_run=True, auth_token=None):
+ self.headers = {
+ "Accept" : "application/json",
+ "Content-Type" : "application/json",
+ }
+ self.dry_run = dry_run
+ self.repo_type = repo_type
+ if repo_type == "stable":
+ repo = "netdata/netdata"
+ elif repo_type == "devel":
+ repo = "netdata/netdata-devel"
+ elif repo_type == "edge":
+ repo = "netdata/netdata-edge"
+ else:
+ print(f"ERROR: unknown repo type '{repo_type}'!\nAccepted values are: stable,devel,edge")
+ sys.exit(1)
+ self.base_url = f"https://packagecloud.io/api/v1/repos/{repo}"
+ self.auth = HTTPBasicAuth(username=auth_token, password='') if auth_token else None
+
+ def get_all_packages(self):
+ page = 1
+ all_pkg_list = []
+ while True:
+ url = f"{self.base_url}/packages.json?page={page}"
+ if page > self.MAX_PAGES and self.MAX_PAGES != 0:
+ break
+ else:
+ pkg_list = requests.get(url, auth=self.auth, headers=self.headers).json()
+ if len(pkg_list) == 0:
+ break
+ else:
+ print(f"Processing page: {page}")
+ for element in pkg_list:
+ self.is_pkg_older_than_days(element, 30)
+ if element['name'] != 'netdata-repo' and element['name'] != 'netdata-repo-edge':
+ all_pkg_list.append(element)
+ page += 1
+ return all_pkg_list
+
+ def delete_package(self, destroy_url):
+ if self.dry_run:
+ print(f" - DRY_RUN mode. Not deleting package '{destroy_url}'.")
+ else:
+ print(f" - Deleting package: {destroy_url}")
+ url = f"https://packagecloud.io{destroy_url}"
+ response = requests.delete(url, auth=self.auth, headers=self.headers).json()
+ response = None
+ if not response:
+ print(f" Package deleted successfully.")
+ else:
+ print(f" Failed deleting package!")
+
+ def get_destroy_url(self, pkg_url):
+ url = f"https://packagecloud.io{pkg_url}"
+ response = requests.get(url, auth=self.auth, headers=self.headers)
+ response.raise_for_status()
+ return response.json()['destroy_url']
+
+ def get_packages_for_distro(self, distro, all_pkg_list):
+ distro_pkg_list = [ pkg for pkg in all_pkg_list if pkg['distro_version'] == distro ]
+ return distro_pkg_list
+
+ def get_packages_for_arch(self, arch, all_pkg_list):
+ arch_pkg_list = [ pkg for pkg in all_pkg_list if pkg['package_url'].split('/')[11] == arch ]
+ return arch_pkg_list
+
+ def get_arches(self, pkg_list):
+ arches = list(set([pkg['package_url'].split('/')[11] for pkg in pkg_list ]))
+ return arches
+
+ def get_pkg_list(self, pkg_name, pkg_list):
+ filtered_list = [ pkg for pkg in pkg_list if pkg['name'] == pkg_name ]
+ return filtered_list
+
+ def get_minor_versions(self, all_versions):
+ minor_versions = ['.'.join(version.split('.')[:-1]) for version in all_versions ]
+ minor_versions = list(set(minor_versions))
+ minor_versions.sort()
+ return minor_versions
+
+ def is_pkg_older_than_days(self, pkg, num_days):
+ pkg_create_date = datetime.strptime(pkg['created_at'], '%Y-%m-%dT%H:%M:%S.%fZ')
+ time_difference = datetime.now() - pkg_create_date
+ return time_difference.days > num_days
+
+ def cleanup_repo(self):
+ if self.repo_type == 'stable':
+ self.cleanup_stable_repo()
+ else:
+ self.cleanup_edge_repo()
+
+ def cleanup_edge_repo(self):
+ all_pkg_list = self.get_all_packages()
+ pkgs_to_delete = []
+ pkgs_to_keep = []
+ for package in all_pkg_list:
+ if self.is_pkg_older_than_days(package, self.NUM_RETENTION_DAYS):
+ pkgs_to_delete.append(package)
+ else:
+ pkgs_to_keep.append(package)
+ print(f"Keeping the following packages (newer than {self.NUM_RETENTION_DAYS} days):")
+ for pkg in pkgs_to_keep:
+ print(f" > pkg: {pkg['package_html_url']} / created_at: {pkg['created_at']}")
+ print(f"Deleting the following packages (older than {self.NUM_RETENTION_DAYS} days):")
+ for pkg in pkgs_to_delete:
+ print(f" > pkg: {pkg['package_html_url']} / created_at: {pkg['created_at']}")
+ self.delete_package(pkg['destroy_url'])
+
+ def cleanup_stable_repo(self):
+ all_pkg_list = self.get_all_packages()
+ all_distros = list(set([ pkg['distro_version'] for pkg in all_pkg_list ]))
+ all_distros = sorted(all_distros)
+ print(f"<> Distributions list: {all_distros}")
+
+ for distro in all_distros:
+ print(f">> Processing distro: {distro}")
+ pkg_list_distro = self.get_packages_for_distro(distro, all_pkg_list)
+ arches = self.get_arches(pkg_list_distro)
+ print(f" <> Arch list: {arches}")
+ for arch in arches:
+ print(f" >> Processing arch: {distro} -> {arch}")
+ pkg_list_arch = self.get_packages_for_arch(arch, pkg_list_distro)
+ pkg_names = [pkg['name'] for pkg in pkg_list_arch]
+ pkg_names = list(set(pkg_names))
+ print(f" <> Package names: {pkg_names}")
+ for pkg_name in pkg_names:
+ print(f" >> Processing package: {distro} -> {arch} -> {pkg_name}")
+ pkg_list = self.get_pkg_list(pkg_name, pkg_list_arch)
+ pkg_versions = [pkg['version'] for pkg in pkg_list]
+ pkg_minor_versions = self.get_minor_versions(pkg_versions)
+ pkg_minor_to_keep = pkg_minor_versions[-self.NUM_PACKAGE_MINOR_TO_KEEP:]
+ print(f" <> Minor Package Versions to Keep: {pkg_minor_to_keep}")
+ pkg_minor_to_delete = list(set(pkg_minor_versions) - set(pkg_minor_to_keep))
+ print(f" <> Minor Package Versions to Delete: {pkg_minor_to_delete}")
+ urls_to_keep = [pkg['package_url'] for pkg in pkg_list if '.'.join(pkg['version'].split('.')[:-1]) in pkg_minor_to_keep]
+ urls_to_delete = [pkg['package_url'] for pkg in pkg_list if '.'.join(pkg['version'].split('.')[:-1]) in pkg_minor_to_delete]
+ for pkg_url in urls_to_delete:
+ destroy_url = self.get_destroy_url(pkg_url)
+ self.delete_package(destroy_url)
+
+
+def configure():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--repo-type', '-r', required=True,
+ help='Repository type against to perform cleanup')
+ parser.add_argument('--dry-run', '-d', action='store_true',
+ help='Dry-run Mode')
+ args = parser.parse_args()
+ try:
+ token = os.environ['PKGCLOUD_TOKEN']
+ except Exception as e:
+ print(f"FATAL: 'PKGCLOUD_TOKEN' environment variable is not set!", file=sys.stderr)
+ sys.exit(1)
+ repo_type = args.repo_type
+ dry_run = args.dry_run
+ conf = {
+ 'repo_type': args.repo_type,
+ 'dry_run': args.dry_run,
+ 'token': token
+ }
+ return conf
+
+
+def main():
+ config = configure()
+ pkg_cloud = PackageCloud(config['repo_type'], config['dry_run'], config['token'])
+ pkg_cloud.cleanup_repo()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.github/scripts/package-upload.sh b/.github/scripts/package-upload.sh
new file mode 100755
index 0000000..fd8a8cd
--- /dev/null
+++ b/.github/scripts/package-upload.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+host="packages.netdata.cloud"
+user="netdatabot"
+
+distro="${1}"
+arch="${2}"
+format="${3}"
+repo="${4}"
+
+staging="${TMPDIR:-/tmp}/package-staging"
+prefix="/home/netdatabot/incoming/${repo}/"
+
+packages="$(find artifacts -name "*.${format}")"
+
+mkdir -p "${staging}"
+
+case "${format}" in
+ deb)
+ src="${staging}/$(echo "${distro}" | cut -f 1 -d '/')/pool/"
+ mkdir -p "${src}"
+
+ for pkg in ${packages}; do
+ cp "${pkg}" "${src}"
+ done
+ ;;
+ rpm)
+ src="${staging}/${distro}/${arch}/"
+ mkdir -p "${src}"
+
+ for pkg in ${packages}; do
+ cp "${pkg}" "${src}"
+ done
+ ;;
+ *)
+ echo "Unrecognized package format ${format}."
+ exit 1
+ ;;
+esac
+
+rsync -vrptO "${staging}/" "${user}@${host}:${prefix}"
diff --git a/.github/scripts/package_cloud_wrapper.sh b/.github/scripts/package_cloud_wrapper.sh
new file mode 100755
index 0000000..7640ef4
--- /dev/null
+++ b/.github/scripts/package_cloud_wrapper.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+#
+# This is a tool to help removal of packages from packagecloud.io
+# It utilizes the package_cloud utility provided from packagecloud.io
+#
+# Depends on:
+# 1) package cloud gem (detects absence and installs it)
+#
+# Requires:
+# 1) PKG_CLOUD_TOKEN variable exported
+# 2) To properly install package_cloud when not found, it requires: ruby gcc gcc-c++ ruby-devel
+#
+# Copyright: SPDX-License-Identifier: GPL-3.0-or-later
+#
+# Author : Pavlos Emm. Katsoulakis (paul@netdata.cloud)
+#shellcheck disable=SC2068,SC2145
+set -e
+PKG_CLOUD_CONFIG="$HOME/.package_cloud_configuration.cfg"
+
+# If we are not in netdata git repo, at the top level directory, fail
+TOP_LEVEL=$(basename "$(git rev-parse --show-toplevel)")
+CWD=$(git rev-parse --show-cdup)
+if [ -n "$CWD" ] || [ ! "${TOP_LEVEL}" == "netdata" ]; then
+ echo "Run as .github/scripts/$(basename "$0") from top level directory of netdata git repository"
+ echo "Docker build process aborted"
+ exit 1
+fi
+
+# Install dependency if not there
+if ! command -v package_cloud > /dev/null 2>&1; then
+ echo "No package cloud gem found, installing"
+ sudo gem install -V package_cloud || (echo "Package cloud installation failed. you might want to check if required dependencies are there (ruby gcc gcc-c++ ruby-devel)" && exit 1)
+else
+ echo "Found package_cloud gem, continuing"
+fi
+
+# Check for required token and prepare config
+if [ -z "${PKG_CLOUD_TOKEN}" ]; then
+ echo "Please set PKG_CLOUD_TOKEN to be able to use ${0}"
+ exit 1
+fi
+echo "{\"url\":\"https://packagecloud.io\",\"token\":\"${PKG_CLOUD_TOKEN}\"}" > "${PKG_CLOUD_CONFIG}"
+
+echo "Executing package_cloud with config ${PKG_CLOUD_CONFIG} and parameters $@"
+package_cloud $@ --config="${PKG_CLOUD_CONFIG}"
+
+rm -rf "${PKG_CLOUD_CONFIG}"
+echo "Done!"
diff --git a/.github/scripts/pkg-test.sh b/.github/scripts/pkg-test.sh
new file mode 100755
index 0000000..e3bc3e7
--- /dev/null
+++ b/.github/scripts/pkg-test.sh
@@ -0,0 +1,138 @@
+#!/bin/sh
+
+install_debian_like() {
+ # This is needed to ensure package installs don't prompt for any user input.
+ export DEBIAN_FRONTEND=noninteractive
+
+ if apt-cache show netcat 2>&1 | grep -q "No packages found"; then
+ netcat="netcat-traditional"
+ else
+ netcat="netcat"
+ fi
+
+ apt-get update
+
+ # Install Netdata
+ apt-get install -y /netdata/artifacts/netdata_"${VERSION}"*_*.deb || exit 1
+
+ # Install testing tools
+ apt-get install -y --no-install-recommends curl "${netcat}" jq || exit 1
+}
+
+install_fedora_like() {
+ # Using a glob pattern here because I can't reliably determine what the
+ # resulting package name will be (TODO: There must be a better way!)
+
+ PKGMGR="$( (command -v dnf > /dev/null && echo "dnf") || echo "yum")"
+
+ pkg_version="$(echo "${VERSION}" | tr - .)"
+
+ # Install Netdata
+ "$PKGMGR" install -y /netdata/artifacts/netdata-"${pkg_version}"-*.rpm
+
+ # Install testing tools
+ "$PKGMGR" install -y curl nc jq || exit 1
+}
+
+install_centos() {
+ # Using a glob pattern here because I can't reliably determine what the
+ # resulting package name will be (TODO: There must be a better way!)
+
+ PKGMGR="$( (command -v dnf > /dev/null && echo "dnf") || echo "yum")"
+
+ pkg_version="$(echo "${VERSION}" | tr - .)"
+
+ if [ "${PKGMGR}" = "dnf" ]; then
+ opts="--allowerasing"
+ fi
+
+ # Install EPEL (needed for `jq`
+ "$PKGMGR" install -y epel-release || exit 1
+
+ # Install Netdata
+ "$PKGMGR" install -y /netdata/artifacts/netdata-"${pkg_version}"-*.rpm
+
+ # Install testing tools
+ "$PKGMGR" install -y ${opts} curl nc jq || exit 1
+}
+
+install_suse_like() {
+ # Using a glob pattern here because I can't reliably determine what the
+ # resulting package name will be (TODO: There must be a better way!)
+
+ pkg_version="$(echo "${VERSION}" | tr - .)"
+
+ # Install Netdata
+ zypper install -y --allow-unsigned-rpm /netdata/artifacts/netdata-"${pkg_version}"-*.rpm
+
+ # Install testing tools
+ zypper install -y --no-recommends curl netcat-openbsd jq || exit 1
+}
+
+dump_log() {
+ cat ./netdata.log
+}
+
+wait_for() {
+ host="${1}"
+ port="${2}"
+ name="${3}"
+ timeout="30"
+
+ if command -v nc > /dev/null ; then
+ netcat="nc"
+ elif command -v netcat > /dev/null ; then
+ netcat="netcat"
+ else
+ printf "Unable to find a usable netcat command.\n"
+ return 1
+ fi
+
+ printf "Waiting for %s on %s:%s ... " "${name}" "${host}" "${port}"
+
+ sleep 30
+
+ i=0
+ while ! ${netcat} -z "${host}" "${port}"; do
+ sleep 1
+ if [ "$i" -gt "$timeout" ]; then
+ printf "Timed out!\n"
+ return 1
+ fi
+ i="$((i + 1))"
+ done
+ printf "OK\n"
+}
+
+case "${DISTRO}" in
+ debian | ubuntu)
+ install_debian_like
+ ;;
+ fedora | oraclelinux)
+ install_fedora_like
+ ;;
+ centos | rockylinux | almalinux)
+ install_centos
+ ;;
+ opensuse)
+ install_suse_like
+ ;;
+ *)
+ printf "ERROR: unsupported distro: %s_%s\n" "${DISTRO}" "${DISTRO_VERSION}"
+ exit 1
+ ;;
+esac
+
+trap dump_log EXIT
+
+/usr/sbin/netdata -D > ./netdata.log 2>&1 &
+
+wait_for localhost 19999 netdata || exit 1
+
+curl -sS http://127.0.0.1:19999/api/v1/info > ./response || exit 1
+
+cat ./response
+
+jq '.version' ./response || exit 1
+
+trap - EXIT
diff --git a/.github/scripts/prepare-release-base.sh b/.github/scripts/prepare-release-base.sh
new file mode 100755
index 0000000..7c24f6b
--- /dev/null
+++ b/.github/scripts/prepare-release-base.sh
@@ -0,0 +1,176 @@
+#!/bin/sh
+
+set -e
+
+REPO="${1}"
+EVENT_NAME="${2}"
+EVENT_TYPE="${3}"
+EVENT_VERSION="${4}"
+RELEASE_TEST="${5}"
+
+##############################################################
+# Version validation functions
+
+check_version_format() {
+ if ! echo "${EVENT_VERSION}" | grep -qE '^v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+$'; then
+ echo "::error::The supplied version (${EVENT_VERSION}) is not a valid version string."
+ return 1
+ fi
+}
+
+patch_is_zero() {
+ if ! echo "${EVENT_VERSION}" | grep -qE '^v[[:digit:]]+\.[[:digit:]]+\.0$'; then
+ echo "::error::The patch number for a ${EVENT_TYPE} build must be 0."
+ return 1
+ fi
+}
+
+minor_is_zero() {
+ if ! echo "${EVENT_VERSION}" | grep -qE '^v[[:digit:]]+\.0'; then
+ echo "::error::The minor version number for a ${EVENT_TYPE} build must be 0."
+ return 1
+ fi
+}
+
+major_matches() {
+ current_major="$(cut -f 1 -d '-' packaging/version | cut -f 1 -d '.' | cut -f 2 -d 'v')"
+ target_major="$(echo "${EVENT_VERSION}" | cut -f 1 -d '.' | cut -f 2 -d 'v')"
+
+ if [ "${target_major}" != "${current_major}" ]; then
+ echo "::error::Major version mismatch, expected ${current_major} but got ${target_major}."
+ return 1
+ fi
+}
+
+minor_matches() {
+ current_minor="$(cut -f 1 -d '-' packaging/version | cut -f 2 -d '.')"
+ target_minor="$(echo "${EVENT_VERSION}" | cut -f 2 -d '.')"
+
+ if [ "${target_minor}" != "${current_minor}" ]; then
+ echo "::error::Minor version mismatch, expected ${current_minor} but got ${target_minor}."
+ return 1
+ fi
+}
+
+check_for_existing_tag() {
+ if git tag | grep -qE "^${EVENT_VERSION}$"; then
+ echo "::error::A tag for version ${EVENT_VERSION} already exists."
+ return 1
+ fi
+}
+
+check_newer_major_version() {
+ current="$(cut -f 1 -d '-' packaging/version | cut -f 1 -d '.' | cut -f 2 -d 'v')"
+ target="$(echo "${EVENT_VERSION}" | cut -f 1 -d '.' | cut -f 2 -d 'v')"
+
+ if [ "${target}" -le "${current}" ]; then
+ echo "::error::Version ${EVENT_VERSION} is not newer than the current version."
+ return 1
+ fi
+}
+
+check_newer_minor_version() {
+ current="$(cut -f 1 -d '-' packaging/version | cut -f 2 -d '.')"
+ target="$(echo "${EVENT_VERSION}" | cut -f 2 -d '.')"
+
+ if [ "${target}" -le "${current}" ]; then
+ echo "::error::Version ${EVENT_VERSION} is not newer than the current version."
+ return 1
+ fi
+}
+
+check_newer_patch_version() {
+ current="$(cut -f 1 -d '-' packaging/version | cut -f 3 -d '.')"
+ target="$(echo "${EVENT_VERSION}" | cut -f 3 -d '.')"
+
+ if [ "${target}" -le "${current}" ]; then
+ echo "::error::Version ${EVENT_VERSION} is not newer than the current version."
+ return 1
+ fi
+}
+
+##############################################################
+# Core logic
+
+git config user.name "netdatabot"
+git config user.email "bot@netdata.cloud"
+
+if [ "${REPO}" != "netdata/netdata" ] && [ -z "${RELEASE_TEST}" ]; then
+ echo "::notice::Not running in the netdata/netdata repository, not queueing a release build."
+ echo "::set-output name=run::false"
+elif [ "${EVENT_NAME}" = 'schedule' ] || [ "${EVENT_TYPE}" = 'nightly' ]; then
+ echo "::notice::Preparing a nightly release build."
+ LAST_TAG=$(git describe --abbrev=0 --tags)
+ COMMITS_SINCE_RELEASE=$(git rev-list "${LAST_TAG}"..HEAD --count)
+ NEW_VERSION="${LAST_TAG}-$((COMMITS_SINCE_RELEASE + 1))-nightly"
+ LAST_VERSION_COMMIT="$(git rev-list -1 HEAD packaging/version)"
+ HEAD_COMMIT="$(git rev-parse HEAD)"
+ if [ "${EVENT_NAME}" = 'schedule' ] && [ "${LAST_VERSION_COMMIT}" = "${HEAD_COMMIT}" ] && grep -qE '.*-nightly$' packaging/version; then
+ echo "::notice::No commits since last nightly build, not publishing a new nightly build."
+ echo "::set-output name=run::false"
+ else
+ echo "${NEW_VERSION}" > packaging/version || exit 1
+ echo "::set-output name=run::true"
+ echo "::set-output name=message::Update changelog and version for nightly build: ${NEW_VERSION}."
+ echo "::set-output name=ref::master"
+ echo "::set-output name=type::nightly"
+ echo "::set-output name=branch::master"
+ echo "::set-output name=version::nightly"
+ fi
+elif [ "${EVENT_TYPE}" = 'patch' ] && [ "${EVENT_VERSION}" != "nightly" ]; then
+ echo "::notice::Preparing a patch release build."
+ check_version_format || exit 1
+ check_for_existing_tag || exit 1
+ branch_name="$(echo "${EVENT_VERSION}" | cut -f 1-2 -d '.')"
+ if ! git checkout "${branch_name}"; then
+ echo "::error::Could not find a branch for the ${branch_name}.x release series."
+ exit 1
+ fi
+ minor_matches || exit 1
+ major_matches || exit 1
+ check_newer_patch_version || exit 1
+ echo "${EVENT_VERSION}" > packaging/version || exit 1
+ echo "::set-output name=run::true"
+ echo "::set-output name=message::Patch release ${EVENT_VERSION}."
+ echo "::set-output name=ref::${EVENT_VERSION}"
+ echo "::set-output name=type::release"
+ echo "::set-output name=branch::${branch_name}"
+ echo "::set-output name=version::$(tr -d 'v' < packaging/version)"
+elif [ "${EVENT_TYPE}" = 'minor' ] && [ "${EVENT_VERSION}" != "nightly" ]; then
+ echo "::notice::Preparing a minor release build."
+ check_version_format || exit 1
+ patch_is_zero || exit 1
+ major_matches || exit 1
+ check_newer_minor_version || exit 1
+ check_for_existing_tag || exit 1
+ branch_name="$(echo "${EVENT_VERSION}" | cut -f 1-2 -d '.')"
+ if [ -n "$(git branch --list "${branch_name}")" ]; then
+ echo "::error::A branch named ${branch_name} already exists in the repository."
+ exit 1
+ fi
+ echo "${EVENT_VERSION}" > packaging/version || exit 1
+ echo "::set-output name=run::true"
+ echo "::set-output name=message::Minor release ${EVENT_VERSION}."
+ echo "::set-output name=ref::${EVENT_VERSION}"
+ echo "::set-output name=type::release"
+ echo "::set-output name=branch::master"
+ echo "::set-output name=new-branch::${branch_name}"
+ echo "::set-output name=version::$(tr -d 'v' < packaging/version)"
+elif [ "${EVENT_TYPE}" = 'major' ] && [ "${EVENT_VERSION}" != "nightly" ]; then
+ echo "::notice::Preparing a major release build."
+ check_version_format || exit 1
+ minor_is_zero || exit 1
+ patch_is_zero || exit 1
+ check_newer_major_version || exit 1
+ check_for_existing_tag || exit 1
+ echo "${EVENT_VERSION}" > packaging/version || exit 1
+ echo "::set-output name=run::true"
+ echo "::set-output name=message::Major release ${EVENT_VERSION}"
+ echo "::set-output name=ref::${EVENT_VERSION}"
+ echo "::set-output name=type::release"
+ echo "::set-output name=branch::master"
+ echo "::set-output name=version::$(tr -d 'v' < packaging/version)"
+else
+ echo '::error::Unrecognized release type or invalid version.'
+ exit 1
+fi
diff --git a/.github/scripts/run-updater-check.sh b/.github/scripts/run-updater-check.sh
new file mode 100755
index 0000000..31ab71d
--- /dev/null
+++ b/.github/scripts/run-updater-check.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+echo ">>> Installing CI support packages..."
+/netdata/.github/scripts/ci-support-pkgs.sh
+echo ">>> Installing Netdata..."
+/netdata/packaging/installer/kickstart.sh --dont-wait --build-only --disable-telemetry || exit 1
+echo "::group::Environment File Contents"
+cat /etc/netdata/.environment
+echo "::endgroup::"
+echo ">>> Updating Netdata..."
+export NETDATA_NIGHTLIES_BASEURL="http://localhost:8080/artifacts/" # Pull the tarball from the local web server.
+/netdata/packaging/installer/netdata-updater.sh --not-running-from-cron --no-updater-self-update || exit 1
+echo ">>> Checking if update was successful..."
+/netdata/.github/scripts/check-updater.sh || exit 1
diff --git a/.github/scripts/run_install_with_dist_file.sh b/.github/scripts/run_install_with_dist_file.sh
new file mode 100755
index 0000000..d59e8b1
--- /dev/null
+++ b/.github/scripts/run_install_with_dist_file.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+#
+# This script is evaluating netdata installation with the source from make dist
+#
+# Copyright: SPDX-License-Identifier: GPL-3.0-or-later
+#
+# Author : Pavlos Emm. Katsoulakis <paul@netdata.cloud)
+
+set -e
+
+if [ $# -ne 1 ]; then
+ printf >&2 "Usage: %s <dist_file>\n" "$(basename "$0")"
+ exit 1
+fi
+
+distfile="${1}"
+shift
+
+printf >&2 "Opening dist archive %s ... " "${distfile}"
+tar -xovf "${distfile}"
+distdir="$(echo "${distfile}" | rev | cut -d. -f3- | rev)"
+cp -a packaging/installer/install-required-packages.sh "${distdir}/install-required-packages.sh"
+if [ ! -d "${distdir}" ]; then
+ printf >&2 "ERROR: %s is not a directory" "${distdir}"
+ exit 2
+fi
+
+printf >&2 "Entering %s and starting docker run ..." "${distdir}"
+
+pushd "${distdir}" || exit 1
+docker run \
+ -e DISABLE_TELEMETRY=1 \
+ -v "${PWD}:/netdata" \
+ -w /netdata \
+ "ubuntu:latest" \
+ /bin/bash -c "./install-required-packages.sh --dont-wait --non-interactive netdata && apt install wget && ./netdata-installer.sh --dont-wait --require-cloud --disable-telemetry --install /tmp --one-time-build && echo \"Validating netdata instance is running\" && wget -O - 'http://127.0.0.1:19999/api/v1/info' | grep version"
+popd || exit 1
+
+echo "All Done!"