aboutsummaryrefslogtreecommitdiffci
path: root/Jenkinsfile
blob: 1ab3e474e63a057e171db5fa120d7cbb9a516f35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Builds are driven by the tag name. The pipeline does nothing at all unless
// the checkout is a tag of the form
//
//     fedora-<fedora_ver>-kernel-<upstream_ver>-patchset-<patchset_ver>
//
// e.g. fedora-45-kernel-7.2.3-patchset-1.
//
// The Fedora version picks the build container and the bucket prefix. The
// kernel and patchset versions are asserted against the spec rather than fed
// into it, so the spec stays the one place they are defined and a mistyped tag
// fails the build instead of publishing something that disagrees with its name.
TAG_PATTERN = /^fedora-(\d+)-kernel-(.+)-patchset-(\d+)$/

// The container image is the one field that has to be known before the agent
// exists, so it cannot be read out of the shell below. Everything between
// `fedora-` and `-kernel-` is the Fedora version, and it never contains a dash.
def fedoraVersionFromTag() {
    def tag = env.TAG_NAME ?: ''
    tag ==~ TAG_PATTERN ? tag.split('-')[1] : null
}

pipeline {
    agent none

    options {
        timestamps()
    }

    environment {
        B2_ENDPOINT = 'https://s3.eu-central-003.backblazeb2.com'
        AWS_DEFAULT_REGION = 'eu-central-003'
        RPM_BUCKET = 'dist-sayagit-fedora-rpm'

        // awscli2 sends CRC32 checksums by default, which B2 rejects. Ask for
        // them only where the S3 API requires them.
        AWS_REQUEST_CHECKSUM_CALCULATION = 'when_required'
        AWS_RESPONSE_CHECKSUM_VALIDATION = 'when_required'
    }

    stages {
        stage('Build and publish kernel-surface RPM (ARM64)') {
            when {
                beforeAgent true
                allOf {
                    buildingTag()
                    expression { env.TAG_NAME ==~ TAG_PATTERN }
                }
            }

            agent {
                kubernetes {
                    defaultContainer 'rpmbuild'
                    yaml """
apiVersion: v1
kind: Pod
metadata:
  namespace: jenkins
spec:
  nodeSelector:
    kubernetes.io/arch: arm64
  containers:
    - name: rpmbuild
      image: fedora:${fedoraVersionFromTag()}
      imagePullPolicy: Always
      command: [ 'sleep' ]
      args: [ 'infinity' ]
      tty: true
      resources:
        requests:
          cpu: "4"
          memory: 5Gi
          ephemeral-storage: 40Gi
        limits:
          memory: 5Gi
          ephemeral-storage: 100Gi
"""
                }
            }
            steps {
                checkout scm
                container('rpmbuild') {
                    withCredentials([usernamePassword(
                        credentialsId: 'backblaze-b2-dist-rpm',
                        usernameVariable: 'AWS_ACCESS_KEY_ID',
                        passwordVariable: 'AWS_SECRET_ACCESS_KEY')]) {
                        sh '''
                            set -eux

                            dnf --assumeyes install \\
                                git rpm-build rpmdevtools dnf5-plugins awscli2 curl tar \\
                                createrepo_c

                            git config --global --add safe.directory '*'
                            git submodule update --init overlay

                            rest=${TAG_NAME#fedora-*-kernel-}
                            tag_fedora=${TAG_NAME#fedora-}
                            tag_fedora=${tag_fedora%%-kernel-*}
                            tag_kernel=${rest%-patchset-*}
                            tag_patchset=${rest##*-patchset-}
                            fedora_version=${tag_fedora}

                            # The tag drives the build: these override the
                            # spec's own %global defaults, and make-sources.sh
                            # reads them out of the environment so the patch
                            # tarball it assembles is the one Source1 names.
                            export UPSTREAM_VER=${tag_kernel}
                            export PATCHSET_VER=${tag_patchset}

                            # A numbered tag has to agree with the container it
                            # selected, which is what stamps %{?dist} onto the
                            # release.
                            container_fedora=$(rpm --eval '%{fedora}')
                            if [ "${tag_fedora}" != "${container_fedora}" ]; then
                                echo "tag names Fedora ${tag_fedora}, container is ${container_fedora}" >&2
                                exit 1
                            fi

                            rpmdev-setuptree

                            # The published file names are whatever the spec
                            # resolves to under the tag's versions, so the two
                            # cannot drift. Note the plural: kernel-surface-dtb
                            # is a separate package because the main one is
                            # installonly and cannot own a path that carries no
                            # kernel version. Publishing only the first would
                            # leave the kernel unresolvable.
                            prefix="s3://${RPM_BUCKET}/fedora/${fedora_version}/aarch64"
                            rpm_files=$(rpmspec -q \\
                                --define "upstream_ver ${UPSTREAM_VER}" \\
                                --define "patchset_ver ${PATCHSET_VER}" \\
                                --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm\\n' \\
                                kernel-surface.spec)

                            # A kernel build is expensive; skip it only when
                            # every one of those is already in the bucket.
                            skip_build=true
                            for rpm_name in ${rpm_files}; do
                                if ! aws s3 ls --endpoint-url "${B2_ENDPOINT}" \\
                                    "${prefix}/${rpm_name}"; then
                                    skip_build=false
                                fi
                            done
                            if [ "${skip_build}" = true ]; then
                                echo "${TAG_NAME} is already published in full, skipping build"
                            fi

                            if [ "${skip_build}" = false ]; then
                                ./make-sources.sh
                                dnf --assumeyes builddep kernel-surface.spec

                                rpmbuild -bb \\
                                    --define "upstream_ver ${UPSTREAM_VER}" \\
                                    --define "patchset_ver ${PATCHSET_VER}" \\
                                    --define '_smp_mflags -j4' \\
                                    kernel-surface.spec

                                # kernel-surface-dtb is noarch, so it lands
                                # in RPMS/noarch rather than RPMS/aarch64; ask
                                # where each one actually is.
                                for rpm_name in ${rpm_files}; do
                                    built=$(find "${HOME}/rpmbuild/RPMS" -type f \\
                                        -name "${rpm_name}" -print -quit)
                                    test -n "${built}"

                                    aws s3 cp --endpoint-url "${B2_ENDPOINT}" \\
                                        "${built}" "${prefix}/${rpm_name}"
                                done
                            fi

                            repo="${WORKSPACE}/repo"

                            mkdir -p "${repo}"
                            aws s3 sync --endpoint-url "${B2_ENDPOINT}" \\
                                --exclude '*' --include '*.rpm' \\
                                "${prefix}/" "${repo}/"

                            createrepo_c --update "${repo}"

                            aws s3 sync --endpoint-url "${B2_ENDPOINT}" \\
                                --exclude 'repomd.xml*' \\
                                "${repo}/repodata/" "${prefix}/repodata/"
                            aws s3 cp --endpoint-url "${B2_ENDPOINT}" \\
                                "${repo}/repodata/repomd.xml" \\
                                "${prefix}/repodata/repomd.xml"

                            # Served next to the repository so that consumers
                            # can `dnf config-manager --add-repo` the URL.
                            sed "s|[$]releasever|${fedora_version}|g" \\
                                kernel-sp12in.repo > "${WORKSPACE}/published.repo"
                            aws s3 cp --endpoint-url "${B2_ENDPOINT}" \\
                                "${WORKSPACE}/published.repo" \\
                                "s3://${RPM_BUCKET}/fedora/${fedora_version}/kernel-sp12in.repo"
                        '''
                    }
                }
            }
        }
    }
}