Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8df085b9ac | |||
| 1f5330da76 |
@@ -8,9 +8,4 @@ dev = [
|
||||
"pytest>=8",
|
||||
"jsonschema>=4",
|
||||
"pyyaml>=6",
|
||||
# tools/build's own script dependencies, so tests can import it
|
||||
"typer",
|
||||
"requests",
|
||||
"hvac",
|
||||
"cerberus",
|
||||
]
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
name: argocd
|
||||
github: argoproj/argo-cd
|
||||
github_release_pattern: ^v3\.3\.
|
||||
description: Declarative GitOps continuous delivery for Kubernetes - command line
|
||||
client.
|
||||
arch: amd64
|
||||
platform: linux
|
||||
maintainer: Argo Project
|
||||
homepage: https://github.com/argoproj/argo-cd
|
||||
license: Apache-2.0
|
||||
dist_tag: true
|
||||
builds:
|
||||
- repository:
|
||||
- almalinux/el9
|
||||
image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest
|
||||
release: 1
|
||||
version: 3.3.14
|
||||
- repository:
|
||||
- fedora/42
|
||||
- fedora/43
|
||||
- fedora/44
|
||||
image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest
|
||||
release: 1
|
||||
version: 3.3.14
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
BASE_URL="https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/github/argoproj/argo-cd/releases/download/v${PACKAGE_VERSION}"
|
||||
|
||||
wget -O /app/argocd "${BASE_URL}/argocd-linux-amd64"
|
||||
wget -O /app/cli_checksums.txt "${BASE_URL}/cli_checksums.txt"
|
||||
|
||||
# Upstream lists the asset name; check it against the local filename.
|
||||
cd /app
|
||||
grep ' argocd-linux-amd64$' cli_checksums.txt | sed 's/argocd-linux-amd64$/argocd/' | sha256sum --check --strict -
|
||||
chmod +x /app/argocd
|
||||
|
||||
mkdir -p /app/completions
|
||||
/app/argocd completion bash > /app/completions/argocd
|
||||
/app/argocd completion zsh > /app/completions/_argocd
|
||||
/app/argocd completion fish > /app/completions/argocd.fish
|
||||
|
||||
envsubst < /app/resources/nfpm.yaml > /app/nfpm.yaml
|
||||
|
||||
nfpm pkg --config /app/nfpm.yaml --target /app/dist --packager rpm
|
||||
@@ -1,48 +0,0 @@
|
||||
# nfpm.yaml
|
||||
|
||||
name: ${PACKAGE_NAME}
|
||||
version: ${PACKAGE_VERSION}
|
||||
release: ${PACKAGE_RELEASE}
|
||||
arch: ${PACKAGE_ARCH}
|
||||
platform: ${PACKAGE_PLATFORM}
|
||||
section: default
|
||||
priority: extra
|
||||
description: "${PACKAGE_DESCRIPTION}"
|
||||
|
||||
maintainer: ${PACKAGE_MAINTAINER}
|
||||
homepage: ${PACKAGE_HOMEPAGE}
|
||||
license: ${PACKAGE_LICENSE}
|
||||
|
||||
disable_globbing: false
|
||||
|
||||
replaces:
|
||||
- argocd
|
||||
|
||||
provides:
|
||||
- argocd
|
||||
|
||||
contents:
|
||||
- src: /app/argocd
|
||||
dst: /usr/bin/argocd
|
||||
file_info:
|
||||
mode: 0755
|
||||
owner: root
|
||||
group: root
|
||||
- src: /app/completions/argocd
|
||||
dst: /usr/share/bash-completion/completions/argocd
|
||||
file_info:
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
- src: /app/completions/_argocd
|
||||
dst: /usr/share/zsh/site-functions/_argocd
|
||||
file_info:
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
- src: /app/completions/argocd.fish
|
||||
dst: /usr/share/fish/vendor_completions.d/argocd.fish
|
||||
file_info:
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
@@ -1,22 +0,0 @@
|
||||
name: go-cache-plugin
|
||||
github: tailscale/go-cache-plugin
|
||||
description: A GOCACHEPROG implementation that backs the Go build cache with S3.
|
||||
arch: amd64
|
||||
platform: linux
|
||||
maintainer: Tailscale
|
||||
homepage: https://github.com/tailscale/go-cache-plugin
|
||||
license: BSD-3-Clause
|
||||
dist_tag: true
|
||||
builds:
|
||||
- repository:
|
||||
- almalinux/el9
|
||||
image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest
|
||||
release: 1
|
||||
version: 2026.7.22
|
||||
- repository:
|
||||
- fedora/42
|
||||
- fedora/43
|
||||
- fedora/44
|
||||
image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest
|
||||
release: 1
|
||||
version: 2026.7.22
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
set -e
|
||||
|
||||
# Upstream publishes no tags or releases; PACKAGE_VERSION dates this commit.
|
||||
COMMIT=3031b5d01c50d2748a32c7c9386ea7049883f38e
|
||||
|
||||
# go.mod requires go 1.26.1
|
||||
export GOTOOLCHAIN=go1.26.1
|
||||
|
||||
# Compile the go-cache-plugin binary using Go
|
||||
GOBIN=/app go install github.com/tailscale/go-cache-plugin/cmd/go-cache-plugin@${COMMIT}
|
||||
|
||||
# Process nfpm.yaml with envsubst
|
||||
envsubst < /app/resources/nfpm.yaml > /app/nfpm.yaml
|
||||
|
||||
# Build the RPM
|
||||
nfpm pkg --config /app/nfpm.yaml --target /app/dist --packager rpm
|
||||
@@ -1,31 +0,0 @@
|
||||
# nfpm.yaml
|
||||
|
||||
name: ${PACKAGE_NAME}
|
||||
version: ${PACKAGE_VERSION}
|
||||
release: ${PACKAGE_RELEASE}
|
||||
arch: ${PACKAGE_ARCH}
|
||||
platform: ${PACKAGE_PLATFORM}
|
||||
section: default
|
||||
priority: extra
|
||||
description: "${PACKAGE_DESCRIPTION}"
|
||||
|
||||
maintainer: ${PACKAGE_MAINTAINER}
|
||||
homepage: ${PACKAGE_HOMEPAGE}
|
||||
license: ${PACKAGE_LICENSE}
|
||||
|
||||
disable_globbing: false
|
||||
|
||||
replaces:
|
||||
- go-cache-plugin
|
||||
|
||||
provides:
|
||||
- go-cache-plugin
|
||||
|
||||
# Files to include in the package
|
||||
contents:
|
||||
- src: /app/go-cache-plugin
|
||||
dst: /usr/bin/go-cache-plugin
|
||||
file_info:
|
||||
mode: 0755
|
||||
owner: root
|
||||
group: root
|
||||
@@ -13,9 +13,9 @@ builds:
|
||||
- almalinux/el8
|
||||
image: git.unkin.net/unkin/almalinux8-rpmbuilder:latest
|
||||
release: 1
|
||||
version: '26.2'
|
||||
version: '26.1'
|
||||
- repository:
|
||||
- almalinux/el9
|
||||
image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest
|
||||
release: 1
|
||||
version: '26.2'
|
||||
version: '26.1'
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
# Download the pre-built RPM from GitHub releases.
|
||||
# Upstream always publishes the release-1 asset (nzbget-<version>-1.x86_64.rpm);
|
||||
# the source URL must use the upstream asset name, not PACKAGE_RELEASE, which
|
||||
# carries the dist tag (e.g. 1.el9) and does not exist upstream. Only the local
|
||||
# output filename is dist-tagged, mirroring the code-server package.
|
||||
# Download the pre-built RPM from GitHub releases
|
||||
curl -L -o /app/dist/nzbget-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.x86_64.rpm \
|
||||
https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/github/nzbgetcom/nzbget/releases/download/v$PACKAGE_VERSION/nzbget-${PACKAGE_VERSION}-1.x86_64.rpm
|
||||
https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/github/nzbgetcom/nzbget/releases/download/v$PACKAGE_VERSION/nzbget-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.x86_64.rpm
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# puppet-initial
|
||||
|
||||
A firstrun bootstrap script and oneshot systemd service that initialises a
|
||||
freshly-provisioned host into Puppet:
|
||||
|
||||
1. Sets the FQDN under `.main.unkin.net`.
|
||||
2. Fetches the Puppet CA certificate from the CA service.
|
||||
3. Registers the node with a noop agent run against the CA.
|
||||
4. Runs the agent a few times against the compile master, then enables the
|
||||
`puppet` service and disables itself.
|
||||
|
||||
## Puppet CA endpoint
|
||||
|
||||
The CA endpoint defaults to the in-cluster puppetserver CA service
|
||||
`puppetca.k8s.syd1.au.unkin.net:8140` (serving the standard
|
||||
`/puppet-ca/v1/certificate/ca` API).
|
||||
|
||||
It is overridable via the environment. The `puppet-initial.service` unit reads
|
||||
`/etc/sysconfig/puppet-initial` (`EnvironmentFile=-`, so the file is optional),
|
||||
which the RPM ships as a commented `%config(noreplace)` example:
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
|-----------------|----------------------------------|-------------------------------------------------------------|
|
||||
| `PUPPETCA_HOST` | `puppetca.k8s.syd1.au.unkin.net` | CA hostname (CA cert fetch + `--server` for registration). |
|
||||
| `PUPPETCA_PORT` | `8140` | CA API port. |
|
||||
|
||||
### Overriding from kickstart
|
||||
|
||||
A kickstart `%post` can point a host at a different CA without rebuilding the
|
||||
RPM by writing the sysconfig file before the service starts:
|
||||
|
||||
```bash
|
||||
%post
|
||||
cat > /etc/sysconfig/puppet-initial <<'EOF'
|
||||
PUPPETCA_HOST=puppetca.k8s.syd1.au.unkin.net
|
||||
PUPPETCA_PORT=8140
|
||||
EOF
|
||||
```
|
||||
@@ -11,9 +11,9 @@ builds:
|
||||
release: '1'
|
||||
repository:
|
||||
- almalinux/el8
|
||||
version: 1.0.5
|
||||
version: 1.0.3
|
||||
- image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest
|
||||
release: '1'
|
||||
repository:
|
||||
- almalinux/el9
|
||||
version: 1.0.5
|
||||
version: 1.0.3
|
||||
|
||||
@@ -15,7 +15,7 @@ license: ${PACKAGE_LICENSE}
|
||||
disable_globbing: false
|
||||
|
||||
depends:
|
||||
- openvox-agent
|
||||
- puppet-agent
|
||||
|
||||
# Files to include in the package
|
||||
contents:
|
||||
@@ -31,13 +31,6 @@ contents:
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
- src: /app/resources/puppet-initial.sysconfig
|
||||
dst: /etc/sysconfig/puppet-initial
|
||||
type: config|noreplace
|
||||
file_info:
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
# Scripts to run during installation/removal (optional)
|
||||
scripts:
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Puppet CA endpoint. Overridable via the environment (systemd reads
|
||||
# /etc/sysconfig/puppet-initial via EnvironmentFile), so kickstart %post can
|
||||
# point a host at a different CA without rebuilding the RPM. Defaults to the
|
||||
# in-cluster puppetserver CA service.
|
||||
PUPPETCA_HOST="${PUPPETCA_HOST:-puppetca.k8s.syd1.au.unkin.net}"
|
||||
PUPPETCA_PORT="${PUPPETCA_PORT:-8140}"
|
||||
|
||||
# Ensure the hostname is set
|
||||
hostnamectl set-hostname $(hostname -s).main.unkin.net
|
||||
grep '^HOSTNAME=' /etc/sysconfig/network | cut -d= -f2 | grep -q '\.' || sed -i 's/^\(HOSTNAME=[^\.]*\)$/\1.main.unkin.net/' /etc/sysconfig/network
|
||||
|
||||
# Install CA for Puppet
|
||||
test -f /etc/puppetlabs/puppet/ssl/certs/ca.pem || mkdir -p /etc/puppetlabs/puppet/ssl/certs && wget --no-check-certificate "https://${PUPPETCA_HOST}:${PUPPETCA_PORT}/puppet-ca/v1/certificate/ca" -O /etc/puppetlabs/puppet/ssl/certs/ca.pem
|
||||
test -f /etc/puppetlabs/puppet/ssl/certs/ca.pem || mkdir -p /etc/puppetlabs/puppet/ssl/certs && wget --no-check-certificate https://puppetca.query.consul:8140/puppet-ca/v1/certificate/ca -O /etc/puppetlabs/puppet/ssl/certs/ca.pem
|
||||
|
||||
# Registering to Puppet server
|
||||
/opt/puppetlabs/bin/puppet agent --test --server "${PUPPETCA_HOST}" --noop --onetime --no-daemonize --verbose
|
||||
/opt/puppetlabs/bin/puppet agent --test --server puppetca.query.consul --noop --onetime --no-daemonize --verbose
|
||||
|
||||
# Running Puppet agent five times with a 30-second gap between each run, stop puppet service at the end of each run
|
||||
for i in {1..5}; do
|
||||
|
||||
@@ -5,7 +5,6 @@ Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
EnvironmentFile=-/etc/sysconfig/puppet-initial
|
||||
ExecStart=/usr/local/bin/puppet-initial
|
||||
RemainAfterExit=true
|
||||
ExecStop=/bin/true
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# Environment overrides for the puppet-initial firstrun bootstrap.
|
||||
# Read by the puppet-initial.service unit (EnvironmentFile=-/etc/sysconfig/puppet-initial).
|
||||
# A kickstart %post can write this file to point a host at a different Puppet CA
|
||||
# without rebuilding the RPM. All values are optional; the defaults below match
|
||||
# the shipped in-cluster puppetserver CA service.
|
||||
|
||||
# Hostname of the Puppet CA service. Used both to fetch the CA certificate
|
||||
# (https://<host>:<port>/puppet-ca/v1/certificate/ca) and as --server for the
|
||||
# initial noop agent registration run.
|
||||
#PUPPETCA_HOST=puppetca.k8s.syd1.au.unkin.net
|
||||
|
||||
# Port the Puppet CA API listens on.
|
||||
#PUPPETCA_PORT=8140
|
||||
@@ -1,76 +0,0 @@
|
||||
"""Tests for the RPM filename tools/build reconstructs when probing artifactapi.
|
||||
|
||||
The expected values below were captured from the real nfpm; they are the names
|
||||
the publish step actually uploads, so the existence probe has to ask for
|
||||
exactly these or it 404s and rebuilds forever.
|
||||
"""
|
||||
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).parent.parent
|
||||
|
||||
_loader = importlib.machinery.SourceFileLoader(
|
||||
"rpmbuilder_build", str(REPO_ROOT / "tools" / "build")
|
||||
)
|
||||
_spec = importlib.util.spec_from_loader(_loader.name, _loader)
|
||||
build = importlib.util.module_from_spec(_spec)
|
||||
_loader.exec_module(build)
|
||||
|
||||
|
||||
# nfpm output for `version: <input>` with release 1, arch amd64
|
||||
NFPM_VERSIONS = [
|
||||
("2025.08.03", "2025.8.3"),
|
||||
("2025.07.13", "2025.7.13"),
|
||||
("1.05.0", "1.5.0"),
|
||||
("10.02.01", "10.2.1"),
|
||||
("0.0.09", "0.0.9"),
|
||||
("0.6.1", "0.6.1"),
|
||||
("1.2.3", "1.2.3"),
|
||||
("1.05", "1.5.0"),
|
||||
("08", "8.0.0"),
|
||||
("1.0.0-rc1", "1.0.0~rc1"),
|
||||
("1.05.0-rc1", "1.5.0~rc1"),
|
||||
("1.0.0-rc.1", "1.0.0~rc.1"),
|
||||
# not semver: nfpm leaves these verbatim, so we must too
|
||||
("1.02.3.4", "1.02.3.4"),
|
||||
("2025.08.03.01", "2025.08.03.01"),
|
||||
("1.2.3.4", "1.2.3.4"),
|
||||
("1.0.0-rc.01", "1.0.0-rc.01"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version,expected", NFPM_VERSIONS)
|
||||
def test_nfpm_rpm_version(version, expected):
|
||||
assert build.nfpm_rpm_version(version) == expected
|
||||
|
||||
|
||||
def test_rpm_file_name_matches_nfpm_output():
|
||||
assert (
|
||||
build.rpm_file_name("nzbget_exporter", "2025.08.03", "1.el9", "amd64")
|
||||
== "nzbget_exporter-2025.8.3-1.el9.x86_64.rpm"
|
||||
)
|
||||
|
||||
|
||||
def test_check_package_exists_probes_published_filename(monkeypatch):
|
||||
"""A zero-padded version must not probe a filename nfpm can never produce."""
|
||||
probed = []
|
||||
|
||||
class _Session:
|
||||
def get(self, url, timeout=None):
|
||||
probed.append(url)
|
||||
return type("R", (), {"status_code": 404})()
|
||||
|
||||
monkeypatch.setattr(build, "_artifactapi_session", _Session())
|
||||
|
||||
assert not build.check_package_exists(
|
||||
"nzbget_exporter", "2025.08.03", "1.el9", "almalinux/el9", "amd64"
|
||||
)
|
||||
expected = (
|
||||
"https://artifactapi.k8s.syd1.au.unkin.net/api/v2/remotes/rpm-vendor-el9"
|
||||
"/files/Packages/nzbget_exporter-2025.8.3-1.el9.x86_64.rpm"
|
||||
)
|
||||
assert probed == [expected]
|
||||
+39
-33
@@ -517,38 +517,37 @@ def get_github_token() -> str:
|
||||
|
||||
# ==================== GITEA API FUNCTIONS ====================
|
||||
|
||||
def nfpm_rpm_version(version: str) -> str:
|
||||
def normalize_version(version: str) -> str:
|
||||
"""
|
||||
Render a metadata version the way nfpm renders it into an RPM filename.
|
||||
|
||||
nfpm re-renders any semver-parseable version: leading zeros are dropped,
|
||||
missing components padded to three, and the prerelease joined with '~'.
|
||||
Anything semver cannot parse (four or more components, non-numeric
|
||||
components, a numeric prerelease identifier with a leading zero) is used
|
||||
verbatim.
|
||||
Normalize version string by removing leading zeros from numeric components.
|
||||
Gitea automatically does this normalization.
|
||||
|
||||
Examples:
|
||||
"2025.08.03" -> "2025.8.3"
|
||||
"1.05" -> "1.5.0"
|
||||
"1.2.3-rc1" -> "1.2.3~rc1"
|
||||
"1.02.3.4" -> "1.02.3.4" (not semver, left alone)
|
||||
"1.05.0" -> "1.5.0"
|
||||
"0.6.1" -> "0.6.1" (no change needed)
|
||||
|
||||
Args:
|
||||
version: Original version string
|
||||
|
||||
Returns:
|
||||
Normalized version string
|
||||
"""
|
||||
core, sep, prerelease = version.partition('-')
|
||||
if sep and not prerelease:
|
||||
return version
|
||||
import re
|
||||
|
||||
components = core.split('.')
|
||||
if len(components) > 3 or not all(c.isdigit() for c in components):
|
||||
return version
|
||||
# Split by common separators and normalize each numeric part
|
||||
parts = re.split(r'([.\-_])', version)
|
||||
normalized_parts = []
|
||||
|
||||
# semver rejects numeric prerelease identifiers with a leading zero
|
||||
if any(i.isdigit() and len(i) > 1 and i.startswith('0')
|
||||
for i in prerelease.split('.')):
|
||||
return version
|
||||
for part in parts:
|
||||
# If this part is purely numeric and has leading zeros, remove them
|
||||
if part.isdigit() and len(part) > 1 and part.startswith('0'):
|
||||
# Remove leading zeros but keep at least one digit
|
||||
normalized_parts.append(str(int(part)))
|
||||
else:
|
||||
normalized_parts.append(part)
|
||||
|
||||
components += ['0'] * (3 - len(components))
|
||||
rendered = '.'.join(str(int(c)) for c in components)
|
||||
return f"{rendered}~{prerelease}" if prerelease else rendered
|
||||
return ''.join(normalized_parts)
|
||||
|
||||
|
||||
def get_rpm_dist_tag(distro: str) -> str:
|
||||
@@ -599,14 +598,6 @@ def get_rpm_arch(arch: str) -> str:
|
||||
return {'amd64': 'x86_64', 'arm64': 'aarch64'}.get(arch, arch)
|
||||
|
||||
|
||||
def rpm_file_name(package_name: str, version: str, release: str, arch: str) -> str:
|
||||
"""Filename nfpm produces for this package, and therefore the published name."""
|
||||
return (
|
||||
f"{package_name}-{nfpm_rpm_version(version)}-{release}"
|
||||
f".{get_rpm_arch(arch)}.rpm"
|
||||
)
|
||||
|
||||
|
||||
def check_package_exists(
|
||||
package_name: str,
|
||||
version: str,
|
||||
@@ -636,7 +627,7 @@ def check_package_exists(
|
||||
|
||||
base_url = os.getenv('ARTIFACTAPI_URL', 'https://artifactapi.k8s.syd1.au.unkin.net')
|
||||
repo = get_vendor_repo(distro)
|
||||
rpm_file = rpm_file_name(package_name, version, release, arch)
|
||||
rpm_file = f"{package_name}-{version}-{release}.{get_rpm_arch(arch)}.rpm"
|
||||
url = f"{base_url}/api/v2/remotes/{repo}/files/Packages/{rpm_file}"
|
||||
|
||||
try:
|
||||
@@ -660,6 +651,21 @@ def check_package_exists(
|
||||
return False
|
||||
|
||||
|
||||
def get_package_full_name(package_name: str, version: str, release: str) -> str:
|
||||
"""
|
||||
Generate the full package name as used in the registry.
|
||||
|
||||
Args:
|
||||
package_name: Package name
|
||||
version: Version string
|
||||
release: Release number
|
||||
|
||||
Returns:
|
||||
Full package name string
|
||||
"""
|
||||
return f"{package_name}-{version}-{release}"
|
||||
|
||||
|
||||
# ==================== DOCKER FUNCTIONS ====================
|
||||
|
||||
def check_docker_available() -> bool:
|
||||
|
||||
Reference in New Issue
Block a user