Optimizations for dependabot and RHEL catalog description

This commit is contained in:
Alexey Pustovalov 2026-03-25 14:46:29 +09:00
parent 2444e093dd
commit 5a5081f0a3
4 changed files with 223 additions and 497 deletions

459
.github/dependabot.yml vendored
View file

@ -1,418 +1,45 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
time: "06:00"
open-pull-requests-limit: 10
- package-ecosystem: "docker"
directory: /Dockerfiles/agent/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent/windows
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent2/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent2/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent2/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent2/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent2/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/agent2/windows
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-base/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-base/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-base/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-base/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-base/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-mysql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-mysql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-mysql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-mysql/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-mysql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-pgsql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-pgsql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-pgsql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-pgsql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-sqlite3/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-sqlite3/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-sqlite3/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-sqlite3/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/build-sqlite3/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/java-gateway/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/java-gateway/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/java-gateway/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/java-gateway/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/java-gateway/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-mysql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-mysql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-mysql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-mysql/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-mysql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-sqlite3/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-sqlite3/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-sqlite3/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-sqlite3/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/proxy-sqlite3/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-mysql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-mysql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-mysql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-mysql/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-mysql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-pgsql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-pgsql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-pgsql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/server-pgsql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/snmptraps/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/snmptraps/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/snmptraps/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/snmptraps/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/snmptraps/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-mysql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-mysql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-mysql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-mysql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-pgsql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-pgsql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-pgsql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-apache-pgsql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-mysql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-mysql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-mysql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-mysql/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-mysql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-pgsql/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-pgsql/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-pgsql/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-nginx-pgsql/ubuntu
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-service/alpine
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-service/centos
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-service/ol
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-service/rhel
schedule:
interval: daily
- package-ecosystem: "docker"
directory: /Dockerfiles/web-service/ubuntu
schedule:
interval: daily
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
time: "06:00"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "github-actions"
- package-ecosystem: "docker"
directories:
- "/Dockerfiles/agent/*"
- "/Dockerfiles/agent2/*"
- "/Dockerfiles/build-base/*"
- "/Dockerfiles/build-mysql/*"
- "/Dockerfiles/build-pgsql/*"
- "/Dockerfiles/build-sqlite3/*"
- "/Dockerfiles/java-gateway/*"
- "/Dockerfiles/proxy-mysql/*"
- "/Dockerfiles/proxy-sqlite3/*"
- "/Dockerfiles/server-mysql/*"
- "/Dockerfiles/server-pgsql/*"
- "/Dockerfiles/snmptraps/*"
- "/Dockerfiles/web-apache-mysql/*"
- "/Dockerfiles/web-apache-pgsql/*"
- "/Dockerfiles/web-nginx-mysql/*"
- "/Dockerfiles/web-nginx-pgsql/*"
- "/Dockerfiles/web-service/*"
schedule:
interval: "weekly"
time: "06:30"
open-pull-requests-limit: 3
labels:
- "dependencies"
- "docker"
groups:
docker-images:
applies-to: version-updates
patterns:
- "*"
group-by: dependency-name

View file

@ -0,0 +1,2 @@
markdown==3.7
requests==2.32.3

View file

@ -1,48 +1,96 @@
import sys
import requests
import json
import markdown
import os
import sys
from pathlib import Path
repository_description = None
import markdown
import requests
if ("DESCRIPTION_FILE" not in os.environ or len(os.environ["DESCRIPTION_FILE"]) == 0):
print("::error::Description file environment variable is not specified")
sys.exit(1)
if ("PYXIS_API_TOKEN" not in os.environ or len(os.environ["PYXIS_API_TOKEN"]) == 0):
print("::error::API token environment variable is not specified")
sys.exit(1)
if ("API_URL" not in os.environ or len(os.environ["API_URL"]) == 0):
print("::error::API URL environment variable is not specified")
sys.exit(1)
if ("PROJECT_ID" not in os.environ or len(os.environ["PROJECT_ID"]) == 0):
print("RedHat project ID environment variable is not specified")
MAX_DESCRIPTION_LEN = 32768
REQUEST_TIMEOUT = 30
##################
def fail(msg: str) -> None:
print(f"::error::{msg}")
sys.exit(1)
if (os.path.isfile(os.environ["DESCRIPTION_FILE"] + '.html')):
file = open(os.environ["DESCRIPTION_FILE"] + '.html', mode='r')
repository_description = file.read()
file.close()
elif (os.path.isfile(os.environ["DESCRIPTION_FILE"] + '.md')):
file = open(os.environ["DESCRIPTION_FILE"] + '.md', mode='r')
markdown_data = file.read()
file.close()
repository_description=markdown.markdown(markdown_data)
if (repository_description is None or len(repository_description) == 0):
print("::error::No description file found")
sys.exit(1)
def get_env(name: str) -> str:
value = os.environ.get(name, "").strip()
if not value:
fail(f"{name} environment variable is not specified")
return value
data = dict()
data['container'] = dict()
data['container']['repository_description'] = repository_description[:32768]
##################
headers = {'accept' : 'application/json', 'X-API-KEY' : os.environ["PYXIS_API_TOKEN"], 'Content-Type' : 'application/json'}
result = requests.patch(os.environ["API_URL"] + os.environ["PROJECT_ID"],
headers = headers,
data = json.dumps(data))
def load_description(file_name: str) -> str:
html_path = Path(f"{file_name}.html")
md_path = Path(f"{file_name}.md")
print("::group::Result")
print("Response code: " + str(result.status_code))
print("Last update date: " + json.loads(result.content)['last_update_date'])
print("::endgroup::")
if html_path.is_file():
with html_path.open("r", encoding="utf-8") as f:
return f.read()
if md_path.is_file():
with md_path.open("r", encoding="utf-8") as f:
markdown_data = f.read()
return markdown.markdown(markdown_data)
fail(f"No description file found: expected '{html_path}' or '{md_path}'")
def main() -> int:
description_file = get_env("DESCRIPTION_FILE")
api_token = get_env("PYXIS_API_TOKEN")
api_url = get_env("API_URL")
project_id = get_env("PROJECT_ID")
repository_description = load_description(description_file)
if not repository_description.strip():
fail("Description file is empty")
was_truncated = len(repository_description) > MAX_DESCRIPTION_LEN
repository_description = repository_description[:MAX_DESCRIPTION_LEN]
payload = {
"container": {
"repository_description": repository_description,
}
}
headers = {
"accept": "application/json",
"X-API-KEY": api_token,
"Content-Type": "application/json",
}
url = f"{api_url}{project_id}"
try:
with requests.Session() as session:
response = session.patch(
url,
headers = headers,
json = payload,
timeout = REQUEST_TIMEOUT,
)
response.raise_for_status()
except requests.RequestException as exc:
fail(f"Request to Pyxis API failed: {exc}")
try:
response_data = response.json()
except ValueError:
fail(f"API returned non-JSON response: {response.text[:500]}")
print("::group::Result")
print(f"Response code: {response.status_code}")
if was_truncated:
print(f"Warning: repository_description was truncated to {MAX_DESCRIPTION_LEN} characters")
print(f"Last update date: {response_data.get('last_update_date', '<missing>')}")
print("::endgroup::")
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -9,19 +9,26 @@ on:
- 'Dockerfiles/*/README.md'
- 'Dockerfiles/*/rhel/README.md'
- '.github/workflows/rhel_registry_description.yml'
- '.github/scripts/rhel_description.py'
- '.github/scripts/requirements-rhel-description.txt'
workflow_dispatch:
concurrency:
group: rhel-description-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
DOCKERFILES_DIRECTORY: "./Dockerfiles"
API_URL: "https://catalog.redhat.com/api/containers/v1/projects/certification/id/"
MATRIX_FILE: "build.json"
PYTHON_REQUIREMENTS_FILE: ".github/scripts/requirements-rhel-description.txt"
defaults:
run:
shell: bash
permissions:
contents: read
contents: read
jobs:
init:
@ -32,6 +39,7 @@ jobs:
outputs:
components: ${{ steps.components.outputs.list }}
zabbix_release: ${{ steps.branch_info.outputs.zabbix_release }}
steps:
- name: Block egress traffic
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
@ -40,54 +48,59 @@ jobs:
egress-policy: block
allowed-endpoints: >
github.com:443
api.github.com:443
- name: Checkout repository
- name: Checkout repository metadata
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 1
sparse-checkout: ${{ env.MATRIX_FILE }}
- name: Check ${{ env.MATRIX_FILE }} file
id: build_exists
env:
MATRIX_FILE: ${{ env.MATRIX_FILE }}
run: |
if [[ ! -f "$MATRIX_FILE" ]]; then
echo "::error::File $MATRIX_FILE is missing"
exit 1
fi
set -Eeuo pipefail
if [[ ! -f "$MATRIX_FILE" ]]; then
echo "::error::File $MATRIX_FILE is missing"
exit 1
fi
- name: Get branch info
id: branch_info
shell: bash
env:
github_ref: ${{ github.ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
run: |
result=false
set -Eeuo pipefail
github_ref=${github_ref##*/}
echo "::group::Branch metadata"
echo "zabbix_release=${GITHUB_REF_NAME//.}"
echo "::endgroup::"
echo "::group::Branch metadata"
echo "zabbix_release=${github_ref//.}"
echo "::endgroup::"
echo "zabbix_release=${github_ref//.}" >> $GITHUB_OUTPUT
echo "zabbix_release=${GITHUB_REF_NAME//.}" >> "$GITHUB_OUTPUT"
- name: Prepare Zabbix component list
id: components
env:
MATRIX_FILE: ${{ env.MATRIX_FILE }}
run: |
component_list=$(jq -r '.components | map_values(select(.rhel == true)) | keys | @json' "$MATRIX_FILE")
set -Eeuo pipefail
echo "::group::Zabbix Component List"
echo "$component_list"
echo "::endgroup::"
component_list="$(jq -rc '.components | map_values(select(.rhel == true)) | keys' "$MATRIX_FILE")"
echo "list=$component_list" >> $GITHUB_OUTPUT
if [[ -z "$component_list" || "$component_list" == "[]" ]]; then
echo "::warning::No RHEL-enabled components found in $MATRIX_FILE"
fi
publish:
name: Initialize build
echo "::group::Zabbix Component List"
echo "$component_list"
echo "::endgroup::"
echo "list=$component_list" >> "$GITHUB_OUTPUT"
update-description:
name: Update description (${{ matrix.component }})
runs-on: ubuntu-latest
needs: init
permissions:
@ -96,6 +109,7 @@ jobs:
fail-fast: false
matrix:
component: ${{ fromJson(needs.init.outputs.components) }}
steps:
- name: Block egress traffic
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
@ -103,55 +117,90 @@ jobs:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
catalog.redhat.com:443
files.pythonhosted.org:443
github.com:443
api.github.com:443
pypi.org:443
files.pythonhosted.org:443
catalog.redhat.com:443
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 1
- name: Variables formating
- name: Format matrix variables
id: var_format
env:
MATRIX_BUILD: ${{ matrix.component }}
run: |
MATRIX_BUILD=${MATRIX_BUILD^^}
MATRIX_BUILD=${MATRIX_BUILD//-/_}
set -Eeuo pipefail
echo "::group::Result"
echo "matrix_build=${MATRIX_BUILD}"
echo "::endgroup::"
echo "matrix_build=${MATRIX_BUILD}" >> $GITHUB_OUTPUT
MATRIX_BUILD="${MATRIX_BUILD^^}"
MATRIX_BUILD="${MATRIX_BUILD//-/_}"
- name: Setup Python 3.x
echo "::group::Result"
echo "matrix_build=${MATRIX_BUILD}"
echo "::endgroup::"
echo "matrix_build=${MATRIX_BUILD}" >> "$GITHUB_OUTPUT"
- name: Check Python requirements file
env:
PYTHON_REQUIREMENTS_FILE: ${{ env.PYTHON_REQUIREMENTS_FILE }}
run: |
set -Eeuo pipefail
if [[ ! -f "$PYTHON_REQUIREMENTS_FILE" ]]; then
echo "::error::File $PYTHON_REQUIREMENTS_FILE is missing"
exit 1
fi
- name: Setup Python 3.12
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: '3.x'
python-version: '3.12'
cache: 'pip'
cache-dependency-path: ${{ env.PYTHON_REQUIREMENTS_FILE }}
- name: Install Python packages
env:
PYTHON_REQUIREMENTS_FILE: ${{ env.PYTHON_REQUIREMENTS_FILE }}
run: |
set -Eeuo pipefail
python -m pip install --upgrade pip
pip install markdown requests
pip install -r "$PYTHON_REQUIREMENTS_FILE"
- name: Check description source
env:
DESCRIPTION_FILE: ${{ format('{0}/{1}/rhel/README', env.DOCKERFILES_DIRECTORY, matrix.component) }}
run: |
set -Eeuo pipefail
if [[ ! -f "${DESCRIPTION_FILE}.html" && ! -f "${DESCRIPTION_FILE}.md" ]]; then
echo "::error::No description file found: ${DESCRIPTION_FILE}.html or ${DESCRIPTION_FILE}.md"
exit 1
fi
- name: Update Red Hat project description
env:
DESCRIPTION_FILE: ${{ format('{0}/{1}/rhel/README', env.DOCKERFILES_DIRECTORY, matrix.component) }}
PROJECT_ID: ${{ secrets[format('RHEL_{0}_{1}_PROJECT', needs.init.outputs.zabbix_release, steps.var_format.outputs.matrix_build)] }}
PROJECT_ID: ${{ secrets[format('RHEL_{0}_{1}_PROJECT', needs.init.outputs.zabbix_release, steps.var_format.outputs.matrix_build)] }}
PYXIS_API_TOKEN: ${{ secrets.REDHAT_API_TOKEN }}
API_URL: ${{ env.API_URL }}
run: |
python ./.github/scripts/rhel_description.py
set -Eeuo pipefail
python ./.github/scripts/rhel_description.py
- name: Red Hat Gatalog URL
- name: Print Red Hat Catalog URL
env:
COMPONENT: ${{ matrix.component }}
MATRIX_FILE: ${{ env.MATRIX_FILE }}
run: |
PROJECT_ID=$(jq -r ".components.\"$COMPONENT\".rhel_project" "$MATRIX_FILE")
set -Eeuo pipefail
echo "::group::URL"
echo "https://catalog.redhat.com/software/containers/${PROJECT_ID}"
echo "::endgroup::"
PROJECT_ID="$(jq -r ".components.\"$COMPONENT\".rhel_project" "$MATRIX_FILE")"
echo "::group::URL"
echo "https://catalog.redhat.com/software/containers/${PROJECT_ID}"
echo "::endgroup::"