Build RPM modular packages #78
This file contains hidden or 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: Build RPM modular packages | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| iteration: | |
| description: "Optional: override package iteration (integer). Leave empty for auto" | |
| required: false | |
| default: "" | |
| php_versions: | |
| description: "Optional: PHP versions (comma-separated, e.g., 8.2,8.5). Leave empty for all" | |
| required: false | |
| default: "" | |
| alma_versions: | |
| description: "Optional: AlmaLinux versions (comma-separated, e.g., 8,10). Leave empty for all" | |
| required: false | |
| default: "" | |
| architectures: | |
| description: "Optional: Architectures (comma-separated, e.g., x86_64,arm64). Leave empty for all" | |
| required: false | |
| default: "" | |
| packages: | |
| description: "Optional: override packages list. Leave empty for default" | |
| required: false | |
| default: "" | |
| debug_tmate: | |
| description: "Open tmate session on failure" | |
| type: boolean | |
| required: false | |
| default: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| setup-matrix: | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request') | |
| permissions: | |
| contents: read | |
| outputs: | |
| matrix: ${{ steps.set-matrix.outputs.matrix }} | |
| steps: | |
| - name: Set up matrix | |
| id: set-matrix | |
| run: | | |
| # Default values | |
| default_php='["8.2","8.3","8.4","8.5"]' | |
| default_alma='["8","9","10"]' | |
| default_arch='["x86_64","arm64"]' | |
| # Parse inputs or use defaults | |
| if [[ -n "${INPUTS_PHP_VERSIONS}" ]]; then | |
| php_versions=$(echo "${INPUTS_PHP_VERSIONS}" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";""))') | |
| else | |
| php_versions=$default_php | |
| fi | |
| if [[ -n "${INPUTS_ALMA_VERSIONS}" ]]; then | |
| alma_versions=$(echo "${INPUTS_ALMA_VERSIONS}" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";""))') | |
| else | |
| alma_versions=$default_alma | |
| fi | |
| if [[ -n "${INPUTS_ARCHITECTURES}" ]]; then | |
| arch_versions=$(echo "${INPUTS_ARCHITECTURES}" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";""))') | |
| else | |
| arch_versions=$default_arch | |
| fi | |
| # Create matrix JSON (compact, single line) | |
| matrix=$(jq -nc \ | |
| --argjson php "$php_versions" \ | |
| --argjson alma "$alma_versions" \ | |
| --argjson arch "$arch_versions" \ | |
| '{"php-version":$php,"alma":$alma,"arch":$arch}') | |
| echo "matrix=$matrix" >> $GITHUB_OUTPUT | |
| env: | |
| INPUTS_PHP_VERSIONS: ${{ inputs.php_versions }} | |
| INPUTS_ALMA_VERSIONS: ${{ inputs.alma_versions }} | |
| INPUTS_ARCHITECTURES: ${{ inputs.architectures }} | |
| build: | |
| needs: setup-matrix | |
| runs-on: ${{ matrix.arch == 'x86_64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }} | |
| container: | |
| image: almalinux:${{ matrix.alma }} | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| BASH_ENV: /tmp/gha-bashenv | |
| ITERATION: ${{ inputs.iteration || '' }} | |
| PACKAGES: ${{ inputs.packages || '' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| persist-credentials: false | |
| - name: Set architecture variables | |
| run: | | |
| if [[ "${MATRIX_ARCH}" == "arm64" ]]; then | |
| echo "RPM_ARCH=aarch64" >> $GITHUB_ENV | |
| else | |
| echo "RPM_ARCH=x86_64" >> $GITHUB_ENV | |
| fi | |
| env: | |
| MATRIX_ARCH: ${{ matrix.arch }} | |
| - name: Install composer | |
| run: | | |
| curl -L https://files.henderkes.com/${RPM_ARCH}-linux/php -o /usr/local/bin/php | |
| chmod +x /usr/local/bin/php | |
| curl -sS https://raw.githubusercontent.com/composer/getcomposer.org/f3108f64b4e1c1ce6eb462b159956461592b3e3e/web/installer | php -- --quiet | |
| mv composer.phar /usr/bin/composer | |
| - name: Install caching dependencies | |
| run: | | |
| dnf -y install tar zstd | |
| - name: Prepare cache directories | |
| run: | | |
| composer config -g cache-dir | |
| mkdir -p /var/cache/dnf | |
| - name: Restore composer cache | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.cache/composer | |
| key: composer-${{ hashFiles('**/composer.lock') }} | |
| restore-keys: | | |
| composer- | |
| - name: Restore DNF cache | |
| id: dnf-restore | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: /var/cache/dnf | |
| key: dnf-${{ matrix.alma }}-${{ matrix.arch }} | |
| - name: Bootstrap container | |
| run: | | |
| dnf -y install epel-release dnf-plugins-core | |
| dnf -y install \ | |
| perl make rpm-build rpm-sign rpmdevtools \ | |
| openssh rsync createrepo_c gpg \ | |
| git jq gzip which sudo xz gcc-toolset-15 | |
| if [[ "${MATRIX_ALMA}" -eq 8 || "${MATRIX_ALMA}" -eq 9 ]]; then | |
| dnf -y install @ruby:3.3 rubygems ruby-devel | |
| source /opt/rh/gcc-toolset-15/enable | |
| touch "$BASH_ENV" | |
| echo 'source /opt/rh/gcc-toolset-15/enable' >> "$BASH_ENV" | |
| else | |
| dnf -y install ruby rubygems ruby-devel | |
| touch "$BASH_ENV" | |
| echo 'source /usr/lib/gcc-toolset/15-env.source' >> "$BASH_ENV" | |
| fi | |
| gem install --no-document fpm | |
| env: | |
| MATRIX_ALMA: ${{ matrix.alma }} | |
| - name: Install re2c | |
| run: | | |
| if [[ "${MATRIX_ALMA}" -eq 9 || "${MATRIX_ALMA}" -eq 10 ]]; then | |
| dnf -y install re2c | |
| else | |
| dnf -y install python39 | |
| curl -L https://github.com/skvadrik/re2c/releases/download/4.3/re2c-4.3.tar.xz | tar xJ | |
| cd re2c-4.3 | |
| ./configure | |
| make -j2 | |
| make install | |
| cd .. | |
| rm -rf re2c-4.3 | |
| fi | |
| env: | |
| MATRIX_ALMA: ${{ matrix.alma }} | |
| - name: Set up SSH key | |
| uses: webfactory/ssh-agent@d4b9b8ff72958532804b70bbe600ad43b36d5f2e # v0.8.0 | |
| with: | |
| ssh-private-key: ${{ secrets.GITHUBRPMHENDERKESPRIVATEKEY }} | |
| - name: Install tmate | |
| run: | | |
| case "${MATRIX_ARCH}" in | |
| x86_64) arch="amd64" ;; | |
| arm64) arch="arm64v8" ;; | |
| esac | |
| dir="tmate-2.4.0-static-linux-$arch" | |
| curl -L "https://github.com/tmate-io/tmate/releases/download/2.4.0/$dir.tar.xz" | tar -xJ -O "$dir/tmate" > /usr/bin/tmate | |
| chmod +x /usr/bin/tmate | |
| env: | |
| MATRIX_ARCH: ${{ matrix.arch }} | |
| - name: Add remote host to known_hosts | |
| run: | | |
| mkdir -p ~/.ssh | |
| cat >> /root/.ssh/known_hosts <<'EOF' | |
| ${{ secrets.DEB_SERVER_IP }} ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPQq0y77dDEtxECVMhCxjcqiV369goMcbInsY/d+F1yXGwqOXQ6RqIEzgaVhgq0joMJT5BiGXNXQ+OI10/KtzGI= | |
| ${{ secrets.DEB_SERVER_IP }} ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2laCc5jifgjL/2zLzgP1E/X3kouXdaZv00KtAV1DOO5umThoWzb16cswnVtjtLUEMIuo9rPLB79xX2Asa+nN3uMgJDANnr/xnhRoI++yOGLga40/O69U88j5x+5FXODscH/k4n85mfcjzm/fZLXcHlb17ibCmU20I3v46sydn95Pp4/ShDvqsHVB4gWEKJ+jStkooUz2H1UZ8ZquNtaPTlmkOeClNj6gxag74P5b9VB6M5YNac2Emi3Nm0dYkc+BL0Qv+NEtFR1lR63DLa3O/NGTALGJYGmTUkjwiv8KygegaKhd2zxESmWhV7eYIPax8zL+GE9sX1Xwwh1huS0vsuwr2dXPP1/q5slz1AQV/lx85fGdiHc0F8RUXwqXbvGxZJheTuC/Mgu0cFzp5gqO4kTP28X+9fokzScBKBCIfObDXrl7rZgTXAA8IQ5gHk1tGchaEOIcDsjdISW5HVOiwocYSwUNMHzuZ08qAulatIywtOGcWVRdvOs7TcvSgfZ0= | |
| ${{ secrets.DEB_SERVER_IP }} ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaB5IjokRHAH0Y9pzVe/Jx3s6cn0OADJ9uTxQQubBMu | |
| EOF | |
| chmod 600 /root/.ssh/known_hosts | |
| - name: Set target folder | |
| run: | | |
| TARGET_DIR="el${MATRIX_ALMA}" | |
| echo "TARGET_DIR=${TARGET_DIR}" >> "$GITHUB_ENV" | |
| env: | |
| MATRIX_ALMA: ${{ matrix.alma }} | |
| - name: Composer install | |
| run: composer install --no-interaction --prefer-dist --no-progress | |
| - name: Download artifact from spc-download.yml | |
| uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 | |
| with: | |
| workflow: spc-download.yml | |
| name: downloads-tarball | |
| - name: Extract with permissions | |
| run: | | |
| mkdir -p downloads | |
| tar -xzf downloads.tar.gz -C downloads | |
| rm downloads.tar.gz | |
| - name: Build PHP | |
| run: | | |
| PACKAGES_FLAG="" | |
| if [[ -n "${PACKAGES}" ]]; then | |
| PACKAGES_FLAG="--packages=${PACKAGES}" | |
| fi | |
| ITERATION_FLAG="" | |
| if [[ -n "${ITERATION}" ]]; then | |
| ITERATION_FLAG="--iteration=${ITERATION}" | |
| fi | |
| php bin/spp all --type=rpm --debuginfo --phpv=${MATRIX_PHP_VERSION} $ITERATION_FLAG $PACKAGES_FLAG | |
| env: | |
| MATRIX_PHP_VERSION: ${{ matrix.php-version }} | |
| - name: Prepare rpm signing | |
| run: | | |
| # Setup GPG | |
| export GNUPGHOME="${HOME}/.gnupg" | |
| mkdir -p "${GNUPGHOME}" | |
| chmod 700 "${GNUPGHOME}" | |
| echo "allow-loopback-pinentry" > "${GNUPGHOME}/gpg-agent.conf" | |
| gpgconf --kill gpg-agent | |
| # Import private key and extract fingerprint | |
| FPR=$(printf '%s' "${{ secrets.DEB_GPG_PRIVATE_KEY }}" \ | |
| | gpg --batch --quiet --with-colons --import-options show-only --import 2>/dev/null \ | |
| | awk -F: '/^fpr:/ {print $10; exit}') | |
| printf '%s' "${{ secrets.DEB_GPG_PRIVATE_KEY }}" | gpg --batch --yes --import | |
| # Configure gpg.conf | |
| { | |
| echo "pinentry-mode loopback" | |
| echo "default-key ${FPR}" | |
| } > "${GNUPGHOME}/gpg.conf" | |
| # Unlock key with passphrase (warmup) | |
| t=$(mktemp); echo warmup > "$t" | |
| gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 \ | |
| --local-user "${FPR}" --sign --output /dev/null "$t" <<<"${{ secrets.DEB_GPG_PASSWORD }}" | |
| rm -f "$t" | |
| # Create ~/.rpmmacros (not /root/.rpmmacros!) | |
| cat > ~/.rpmmacros <<EOF | |
| %_signature gpg | |
| %_gpg_path ${GNUPGHOME} | |
| %_gpg_name ${FPR} | |
| %_gpgbin /usr/bin/gpg | |
| %__gpg /usr/bin/gpg | |
| %__gpg_check_password_cmd /bin/true | |
| EOF | |
| - name: Sign RPM packages | |
| run: | | |
| for rpm in dist/rpm/*.rpm; do | |
| rpmsign --addsign "$rpm" | |
| done | |
| - name: Upload packages | |
| run: | | |
| rsync -av --ignore-existing dist/rpm/*.rpm github@${{ secrets.DEB_SERVER_IP }}:/mnt/data/rpm/${RPM_ARCH}/${TARGET_DIR}/ | |
| - name: Upload logs | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: build-logs-${{ matrix.arch }}-el${{ matrix.alma }}-php${{ matrix.php-version }} | |
| path: log | |
| - name: Setup tmate session | |
| if: ${{ failure() && inputs.debug_tmate == true }} | |
| uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3 | |
| with: | |
| install-dependencies: false | |
| sudo: false | |
| timeout-minutes: 30 | |
| setup-update-matrix: | |
| runs-on: ubuntu-24.04 | |
| needs: build | |
| if: ${{ always() }} | |
| outputs: | |
| matrix: ${{ steps.set-matrix.outputs.matrix }} | |
| steps: | |
| - name: Set up matrix | |
| id: set-matrix | |
| run: | | |
| # Default values | |
| default_alma='["8","9","10"]' | |
| default_arch='["x86_64","arm64"]' | |
| # Parse inputs or use defaults | |
| if [[ -n "${GITHUB_EVENT_INPUTS_ALMA_VERSIONS}" ]]; then | |
| alma_versions=$(echo "${GITHUB_EVENT_INPUTS_ALMA_VERSIONS}" | jq -Rc 'split(",") | map(gsub("^\\s+|\\s+$";""))') | |
| else | |
| alma_versions=$default_alma | |
| fi | |
| if [[ -n "${GITHUB_EVENT_INPUTS_ARCHITECTURES}" ]]; then | |
| arch_versions=$(echo "${GITHUB_EVENT_INPUTS_ARCHITECTURES}" | jq -Rc 'split(",") | map(gsub("^\\s+|\\s+$";""))') | |
| else | |
| arch_versions=$default_arch | |
| fi | |
| # Create matrix JSON (compact, single line) | |
| matrix=$(jq -nc \ | |
| --argjson alma "$alma_versions" \ | |
| --argjson arch "$arch_versions" \ | |
| '{"alma":$alma,"arch":$arch}') | |
| echo "matrix=$matrix" >> $GITHUB_OUTPUT | |
| env: | |
| GITHUB_EVENT_INPUTS_ALMA_VERSIONS: ${{ github.event.inputs.alma_versions }} | |
| GITHUB_EVENT_INPUTS_ARCHITECTURES: ${{ github.event.inputs.architectures }} | |
| update-repo: | |
| runs-on: ubuntu-24.04 | |
| needs: setup-update-matrix | |
| if: ${{ always() }} | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.setup-update-matrix.outputs.matrix) }} | |
| steps: | |
| - name: Set architecture variables | |
| run: | | |
| if [[ "${MATRIX_ARCH}" == "arm64" ]]; then | |
| echo "RPM_ARCH=aarch64" >> $GITHUB_ENV | |
| else | |
| echo "RPM_ARCH=x86_64" >> $GITHUB_ENV | |
| fi | |
| env: | |
| MATRIX_ARCH: ${{ matrix.arch }} | |
| - name: Set target folder | |
| run: | | |
| TARGET_DIR="el${MATRIX_ALMA}" | |
| echo "TARGET_DIR=${TARGET_DIR}" >> "$GITHUB_ENV" | |
| env: | |
| MATRIX_ALMA: ${{ matrix.alma }} | |
| - name: Set up SSH key | |
| uses: webfactory/ssh-agent@d4b9b8ff72958532804b70bbe600ad43b36d5f2e # v0.8.0 | |
| with: | |
| ssh-private-key: ${{ secrets.GITHUBRPMHENDERKESPRIVATEKEY }} | |
| - name: Add remote host to known_hosts | |
| run: | | |
| mkdir -p ~/.ssh | |
| cat >> ~/.ssh/known_hosts <<'EOF' | |
| ${{ secrets.DEB_SERVER_IP }} ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPQq0y77dDEtxECVMhCxjcqiV369goMcbInsY/d+F1yXGwqOXQ6RqIEzgaVhgq0joMJT5BiGXNXQ+OI10/KtzGI= | |
| ${{ secrets.DEB_SERVER_IP }} ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2laCc5jifgjL/2zLzgP1E/X3kouXdaZv00KtAV1DOO5umThoWzb16cswnVtjtLUEMIuo9rPLB79xX2Asa+nN3uMgJDANnr/xnhRoI++yOGLga40/O69U88j5x+5FXODscH/k4n85mfcjzm/fZLXcHlb17ibCmU20I3v46sydn95Pp4/ShDvqsHVB4gWEKJ+jStkooUz2H1UZ8ZquNtaPTlmkOeClNj6gxag74P5b9VB6M5YNac2Emi3Nm0dYkc+BL0Qv+NEtFR1lR63DLa3O/NGTALGJYGmTUkjwiv8KygegaKhd2zxESmWhV7eYIPax8zL+GE9sX1Xwwh1huS0vsuwr2dXPP1/q5slz1AQV/lx85fGdiHc0F8RUXwqXbvGxZJheTuC/Mgu0cFzp5gqO4kTP28X+9fokzScBKBCIfObDXrl7rZgTXAA8IQ5gHk1tGchaEOIcDsjdISW5HVOiwocYSwUNMHzuZ08qAulatIywtOGcWVRdvOs7TcvSgfZ0= | |
| ${{ secrets.DEB_SERVER_IP }} ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaB5IjokRHAH0Y9pzVe/Jx3s6cn0OADJ9uTxQQubBMu | |
| EOF | |
| chmod 600 ~/.ssh/known_hosts | |
| - name: Update repository metadata | |
| run: | | |
| ssh github@${{ secrets.DEB_SERVER_IP }} "cd /mnt/data/rpm/${RPM_ARCH}/${TARGET_DIR}/ && createrepo_static && createrepo_c --update . && modifyrepo_c --mdtype=modules modules.yaml repodata/" |