Skip to content

refactor: harden inputs and secret usage #2

refactor: harden inputs and secret usage

refactor: harden inputs and secret usage #2

Workflow file for this run

---

Check failure on line 1 in .github/workflows/copr-ci.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/copr-ci.yml

Invalid workflow file

(Line: 160, Col: 22): Unrecognized named-value: 'env'. Located at position 1 within expression: env.INPUTS_JOB_TIMEOUT, (Line: 160, Col: 22): Unexpected value '${{ env.INPUTS_JOB_TIMEOUT }}'
name: CI Copr Call
permissions:
contents: read
on:
workflow_call:
inputs:
copr_pr_webhook_token:
description: 'Copr PR webhook key. This should not be secret if you want it to work for PRs from forks.'
required: true
type: string
github_org_owner:
description: 'GitHub organization owner. This will prevent user forks from triggering the workflow.'
required: true
type: string
copr_ownername:
description: 'User or group name.'
required: true
type: string
auto_update_package:
description: 'Automatically create/update a package in Copr.'
required: false
type: boolean
default: true
job_timeout:
description: 'Job timeout in minutes.'
required: false
type: number
default: 90
secrets:
COPR_BETA_WEBHOOK_TOKEN:
description: 'Copr beta webhook token. This should be a secret.'
required: true
COPR_STABLE_WEBHOOK_TOKEN:
description: 'Copr stable webhook token. This should be a secret.'
required: true
COPR_CLI_CONFIG:
description: 'Copr CLI configuration file. See https://copr.fedorainfracloud.org/api'
required: true
env:
INPUTS_AUTO_UPDATE_PACKAGE: ${{ inputs.auto_update_package }}
INPUTS_COPR_PR_WEBHOOK_TOKEN: ${{ inputs.copr_pr_webhook_token }}
INPUTS_COPR_OWNERNAME: ${{ inputs.copr_ownername }}
INPUTS_GITHUB_ORG_OWNER: ${{ inputs.github_org_owner }}
INPUTS_JOB_TIMEOUT: ${{ inputs.job_timeout }}
SECRETS_COPR_BETA_WEBHOOK_TOKEN: ${{ secrets.COPR_BETA_WEBHOOK_TOKEN }}
SECRETS_COPR_STABLE_WEBHOOK_TOKEN: ${{ secrets.COPR_STABLE_WEBHOOK_TOKEN }}
SECRETS_COPR_CLI_CONFIG: ${{ secrets.COPR_CLI_CONFIG }}
jobs:
package-init:
name: Create/update copr package
runs-on: ubuntu-latest
container: fedora:latest
env:
BASE_URL: https://copr.fedorainfracloud.org/api_3
PACKAGE_NAME: ${{ github.event.repository.name }}
SOURCE_TYPE_TEXT: "custom"
steps:
- name: Debug inputs
run: |
echo "inputs:"
echo "copr_pr_webhook_token: ${INPUTS_COPR_PR_WEBHOOK_TOKEN}"
echo "github_org_owner: ${INPUTS_GITHUB_ORG_OWNER}"
echo "copr_ownername: ${INPUTS_COPR_OWNERNAME}"
echo "auto_update_package: ${INPUTS_AUTO_UPDATE_PACKAGE}"
echo "job_timeout: ${INPUTS_JOB_TIMEOUT}"
- name: Test secrets
id: test_secrets
if: >
github.repository_owner == env.INPUTS_GITHUB_ORG_OWNER &&
env.INPUTS_AUTO_UPDATE_PACKAGE == 'true'
run: |
# return if secrets.COPR_CLI_CONFIG is empty
if [ -z "${SECRETS_COPR_CLI_CONFIG}" ]; then
echo "Copr CLI configuration file is empty. Exiting..."
# if a pull request exit with 0
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "SKIP_REMAINING_JOBS=true" >> "${GITHUB_OUTPUT}"
else
exit 1
fi
else
mkdir -p ~/.config
echo "${SECRETS_COPR_CLI_CONFIG}" > ~/.config/copr
fi
- name: Install dependencies
if: steps.test_secrets.outputs.SKIP_REMAINING_JOBS != 'true'
run: |
dnf install -y \
copr-cli \
jq
- name: create packages
if: steps.test_secrets.outputs.SKIP_REMAINING_JOBS != 'true'
run: |
projects=(
"pulls"
"beta"
"stable"
)
# download the latest copr-ci.sh script
if [ "${{ github.repository }}" = "LizardByte/copr-ci" ]; then
# use the version from the same ref
ref="${{ github.ref }}"
else
ref="master" # default to master branch
fi
curl \
-fsSL \
--retry 3 \
"https://raw.githubusercontent.com/lizardbyte/copr-ci/${ref}/copr-ci.sh" \
-o copr-ci.sh
# set parameters for package creation
script="copr-ci.sh"
builddeps="git jq python3 rpmlint"
resultdir=""
chroot="fedora-latest-x86_64"
for project in "${projects[@]}"; do
# check if 404 on get package (package does not exist)
url_query="ownername=${INPUTS_COPR_OWNERNAME}&projectname=${project}&packagename=${PACKAGE_NAME}"
url="${BASE_URL}/package?${url_query}"
status_code=$(curl --write-out '%{http_code}' --silent --output /dev/null "${url}")
if [[ "$status_code" == 404 ]]; then
echo "Creating package for ${project}..."
command="add-package-custom"
else
echo "Editing package for ${project}..."
command="edit-package-custom"
fi
copr-cli \
${command} \
--script "${script}" \
--script-builddeps "${builddeps}" \
--script-resultdir "${resultdir}" \
--script-chroot "${chroot}" \
--name "${PACKAGE_NAME}" \
--timeout $((60 * ${INPUTS_JOB_TIMEOUT})) \
"${project}"
done
build:
name: Copr build
needs: package-init
if: github.repository_owner == env.INPUTS_GITHUB_ORG_OWNER
runs-on: ubuntu-latest
container: fedora:latest
timeout-minutes: ${{ env.INPUTS_JOB_TIMEOUT }}
outputs:
BUILD_ID: ${{ steps.build.outputs.BUILD_ID }}
BUILD_CANCEL: ${{ steps.build.outcome == 'cancelled' }}
BUILD_SUCCESS: ${{ steps.build.outcome == 'success' }}
steps:
- name: Install dependencies
run: |
dnf install -y \
copr-cli \
git \
jq \
nodejs \
zip
- name: Checkout
uses: actions/checkout@v5
- name: Set git safe directory
run: git config --global --add safe.directory '*'
- name: Add problem matchers
run: |
# add default matchers
mkdir -p .github/matchers
# download the latest rpmlint.json matcher
if [ ! "${{ github.repository }}" = "LizardByte/copr-ci" ]; then
# not in copr-ci repo, so download the rpmlint.json
ref="master" # default to master branch
curl \
-fsSL \
--retry 3 \
"https://raw.githubusercontent.com/lizardbyte/copr-ci/${ref}/.github/matchers/rpmlint.json" \
-o ".github/matchers/rpmlint.json"
fi
echo "::add-matcher::.github/matchers/rpmlint.json"
# repo specific matchers
if [ -f ".github/matchers/copr-ci.json" ]; then
echo "Found copr-ci.json matcher, adding it..."
echo "::add-matcher::.github/matchers/copr-ci.json"
fi
- name: Get properties
run: |
# package name = repository name
package=${{ github.event.repository.name }}
copr_base="https://copr.fedorainfracloud.org/webhooks/custom-dir/${INPUTS_COPR_OWNERNAME}"
# release and released type
if [ "${{ github.event_name }}" = "release" ]; then
if [ "${{ github.event.action }}" = "prereleased" ]; then
BUILD_CHANNEL="beta"
COPR_PUSH_WEBHOOK="${copr_base}/${BUILD_CHANNEL}/${SECRETS_COPR_BETA_WEBHOOK_TOKEN}/${package}/"
elif [ "${{ github.event.action }}" = "released" ]; then
BUILD_CHANNEL="stable"
COPR_PUSH_WEBHOOK="${copr_base}/${BUILD_CHANNEL}/${SECRETS_COPR_STABLE_WEBHOOK_TOKEN}/${package}/"
fi
elif [ "${{ github.event_name }}" = "pull_request" ]; then
BUILD_CHANNEL="pulls:pr:${{ github.event.number }}"
COPR_PR_WEBHOOK="${copr_base}/${BUILD_CHANNEL}/${INPUTS_COPR_PR_WEBHOOK_TOKEN}/${package}/"
fi
{
echo "BUILD_CHANNEL=${BUILD_CHANNEL}"
echo "COPR_PUSH_WEBHOOK=${COPR_PUSH_WEBHOOK}"
echo "COPR_PR_WEBHOOK=${COPR_PR_WEBHOOK}"
} >> "${GITHUB_ENV}"
echo "BUILD_CHANNEL=${BUILD_CHANNEL}"
echo "COPR_PUSH_WEBHOOK=${COPR_PUSH_WEBHOOK}"
echo "COPR_PR_WEBHOOK=${COPR_PR_WEBHOOK}"
- name: Build
id: build
run: |
curl \
-fsSL \
--retry 3 \
"https://raw.githubusercontent.com/reenignearcher/copr-ci-tooling/patch-1/copr-gh-actions-submit" > submit
# TODO: https://github.com/praiskup/copr-ci-tooling/pull/1
# "https://raw.githubusercontent.com/praiskup/copr-ci-tooling/main/copr-gh-actions-submit"
# if a PR number is added the script will use the PR webhook, otherwise it will use the push webhook
bash submit ${{ github.event.pull_request.number }}
- name: Cancel Copr build
if: >-
always() &&
steps.build.outcome == 'cancelled' &&
github.secret_source
run: |
mkdir -p ~/.config
echo "${SECRETS_COPR_CLI_CONFIG}" > ~/.config/copr
copr-cli \
cancel \
${{ steps.build.outputs.BUILD_ID }}
- name: Logs
if: >-
always() &&
steps.build.outcome != 'skipped'
run: |
package=${{ github.event.repository.name }}
base_url="https://download.copr.fedorainfracloud.org/results/${INPUTS_COPR_OWNERNAME}/${BUILD_CHANNEL}"
# get chroots and prefixed build_id
build_url="https://copr.fedorainfracloud.org/api_3/build/${{ steps.build.outputs.BUILD_ID }}"
data=$(curl -fsSL --retry 3 "${build_url}")
# Extract build_id from source_package.url (matches the last path segment after 'srpm-builds/')
build_id=$(echo "${data}" | jq -r '.source_package.url' | sed -E 's#.*/srpm-builds/([0-9]+)/.*#\1#')
echo "build_id: ${build_id}"
# Extract chroots
chroots=$(echo "${data}" | jq -r '.chroots[]')
echo "chroots:"
echo "${chroots}"
# Array of "name|url" pairs
logs=(
"source_builder|${base_url}/srpm-builds/${build_id}/builder-live.log.gz"
"source_backend|${base_url}/srpm-builds/${build_id}/backend.log.gz"
"import|https://copr-dist-git.fedorainfracloud.org/per-task-logs/${{ steps.build.outputs.BUILD_ID }}.log"
)
for chroot in $chroots; do
logs+=("builder_${chroot}|${base_url}/${chroot}/${build_id}-${package}/builder-live.log.gz")
logs+=("backend_${chroot}|${base_url}/${chroot}/${build_id}-${package}/backend.log.gz")
done
error=0
for entry in "${logs[@]}"; do
name="${entry%%|*}"
url="${entry#*|}"
set +e
echo "::group::Logs - ${name}"
[[ "${url}" == *.gz ]] && \
(curl -fsSL --retry 3 "${url}" | gunzip -c) || \
curl -fsSL --retry 3 "${url}" || {
echo "Failed to download logs from ${url}"
error=1
}
echo "::endgroup::"
set -e
done
exit ${error}
- name: Download build
id: download-build
if: steps.build.outcome == 'success'
run: |
mkdir -p artifacts
copr-cli \
download-build \
--dest . \
--rpms \
${{ steps.build.outputs.BUILD_ID }}
- name: Setup gh actions artifact client
id: download-build-client
if: steps.download-build.outcome == 'success'
uses: lhotari/gh-actions-artifact-client@v2
- name: Upload artifacts
if: steps.download-build-client.outcome == 'success'
run: |
find . -type f -name "*.rpm" ! -name "*.src.rpm" | while read -r file; do
name=build-$(basename "$file")
echo "Uploading $name, file: $file"
zip -j - "$file" | gh-actions-artifact-client.js upload "${name}" --retentionDays=7
done