Skip to content

Merge pull request #19 from elabit/feat/os-centos #83

Merge pull request #19 from elabit/feat/os-centos

Merge pull request #19 from elabit/feat/os-centos #83

Workflow file for this run

name: Run Suites
on:
push:
branches: ["main", "compat/**"]
paths:
- "examples/**"
- "templates/**"
- "os/**"
pull_request:
paths:
- "examples/**"
- "templates/**"
- "os/**"
workflow_dispatch:
inputs:
suite:
description: "Single suite to test, with parent folder (e.g. examples/cryptolibrary)"
required: false
default: ""
jobs:
# ── Stage 1: detect which suites changed ──────────────────────────────────
detect-changes:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Detect changed suites
id: set-matrix
run: |
# Manual trigger with explicit suite override
if [[ -n "${{ github.event.inputs.suite }}" ]]; then
echo "matrix=[\"${{ github.event.inputs.suite }}\"]" >> "$GITHUB_OUTPUT"
exit 0
fi
# Detect changed folders under examples/ and templates/
CHANGED=$(git diff --name-only HEAD~1 HEAD \
| grep -E '^(examples|templates)/' \
| cut -d/ -f1-2 \
| sort -u \
| jq -R . | jq -sc .)
# Fall back to all examples + templates if nothing detected (e.g. first commit)
if [[ "${CHANGED}" == "[]" || -z "${CHANGED}" ]]; then
CHANGED=$(ls -d examples/*/ templates/*/ 2>/dev/null | sed 's|/$||' | jq -R . | jq -sc .)
fi
echo "Before blacklist filtering: ${CHANGED}"
# Apply blacklist (.github/test-blacklist.txt)
BLACKLIST=$(grep -v '^\s*#' .github/test-blacklist.txt | grep -v '^\s*$' || true)
echo "Blacklist: ${BLACKLIST}"
if [[ -n "${BLACKLIST}" ]]; then
CHANGED=$(echo "${CHANGED}" | jq -c --arg bl "${BLACKLIST}" '
($bl | split("\n") | map(select(length > 0))) as $blacklist |
map(select(. as $s | $blacklist | index($s) | not))
')
echo "After blacklist filtering: ${CHANGED}"
fi
echo "matrix=${CHANGED}" >> "$GITHUB_OUTPUT"
echo "Suites to test: ${CHANGED}"
# ── Stage 2: test matrix (os × suite) ─────────────────────────────────────
test:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.matrix != '[]' }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
# We have 2 OS and want to run max 1 job per OS (make use of pre-build RCC environments!)
max-parallel: 2
matrix:
suite: ${{ fromJson(needs.detect-changes.outputs.matrix) }}
os: [ubuntu-latest, windows-latest]
# os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Read RMKS environment from .env
id: suite-env
shell: bash
run: |
ENV_FILE="${{ matrix.suite }}/.env"
SPACE=$(grep '^RMKS_ENVIRONMENT=' "${ENV_FILE}" | cut -d= -f2 | tr -d '[:space:]')
if [[ -z "${SPACE}" ]]; then
echo "ERROR: RMKS_ENVIRONMENT is missing in ${ENV_FILE}" >&2
exit 1
fi
echo "space=${SPACE}" >> "$GITHUB_OUTPUT"
# Sanitize matrix.suite (e.g. examples/cryptolibrary → examples-cryptolibrary)
echo "safe_name=$(echo '${{ matrix.suite }}' | tr '/' '-')" >> "$GITHUB_OUTPUT"
- name: Download RCC
shell: bash
run: |
BASE="https://github.com/elabit/robotmk/releases/download/v4.0.0"
if [[ "${{ runner.os }}" == "Windows" ]]; then
curl -fsSL -o rcc.exe "${BASE}/rcc_windows64.exe"
echo "RCC_BIN=./rcc.exe" >> "$GITHUB_ENV"
else
curl -fsSL -o rcc "${BASE}/rcc_linux64"
chmod +x rcc
echo "RCC_BIN=./rcc" >> "$GITHUB_ENV"
fi
${RCC_BIN:-./rcc} --version
- name: Cache RCC holotree environment
uses: actions/cache@v4
with:
path: ~/.robocorp/holotree
key: rcc-holotree-${{ steps.suite-env.outputs.space }}-${{ runner.os }}
- name: Build RCC holotree environment
shell: bash
run: |
$RCC_BIN holotree vars \
--space ${{ steps.suite-env.outputs.space }} \
--robot ${{ matrix.suite }}/robot.yaml
- name: Load .env if present
shell: bash
run: |
ENV_FILE="${{ matrix.suite }}/.env"
if [[ -f "${ENV_FILE}" ]]; then
echo "Loading variables from ${ENV_FILE}"
grep -v '^\s*#' "${ENV_FILE}" | grep -v '^\s*$' >> "$GITHUB_ENV"
fi
echo "Environment variables set for this suite:"
grep -v '^\s*#' "${ENV_FILE}" | grep -v '^\s*$' || echo "No .env file or no variables found."
# - name: Setup tmate session
# uses: mxschmitt/action-tmate@v3
- name: Run Robot Framework suite
shell: bash
run: |
$RCC_BIN task script \
--space ${{ steps.suite-env.outputs.space }} \
--robot ${{ matrix.suite }}/robot.yaml \
-- robot .
- name: Upload RF output artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: rf-output-${{ steps.suite-env.outputs.safe_name }}-${{ matrix.os }}
path: ${{ matrix.suite }}/log.html
if-no-files-found: ignore
# ── Stage 3: os content type (provision + verify + report) ────────────────
# Independent of the detect-changes/test pair above: exactly one job per OS
# family, added deliberately one epic at a time (Story 1.5 adds debian;
# Stories 2.2/3.2/4.2 each add one more matrix entry; centos is a later
# addition sharing the redhat family with rhel), never auto-detected from a
# directory listing the way the examples/templates matrix is.
os:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
slug: [debian, ubuntu, rhel, sles, centos]
steps:
- uses: actions/checkout@v4
- name: Read pinned image from the generated devcontainer.json
id: os-env
run: |
# devcontainer.json is JSONC (allows // comments, per the Dev
# Container spec) -- jq can't parse that directly, so strip
# line-comments before feeding it to a JSON parser.
IMAGE=$(python3 -c "
import json, re
text = open('os/${{ matrix.slug }}/.devcontainer/devcontainer.json').read()
text = re.sub(r'//.*', '', text)
print(json.loads(text)['image'])
")
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
- name: Provision, verify, and report
run: |
# Mount ONLY os/<slug> (not the full repo root) -- this instance is
# self-contained (its own copy of the shared Ansible role + RF
# suite via populate.yaml, AD-3/AD-4), so this deliberately mirrors
# exactly what a standalone extracted repo would see, proving the
# self-containment property in CI rather than assuming it.
# No devcontainer CLI in CI (AD-9), so its onCreateCommand/
# postCreateCommand split isn't applied automatically here -- chain
# the same two scripts explicitly instead. `&&` gives the identical
# halt-then-propagate semantics the Dev Container lifecycle gives
# the interactive path: postcreate.sh only runs if oncreate.sh
# succeeded, and the final exit code reflects whichever of the two
# actually failed.
docker run --rm \
-v "${{ github.workspace }}/os/${{ matrix.slug }}:/workspace" \
-w "/workspace" \
"${{ steps.os-env.outputs.image }}" \
bash -c "bash .devcontainer/oncreate.sh && bash .devcontainer/postcreate.sh"
- name: Upload install report
if: always()
uses: actions/upload-artifact@v4
with:
name: os-report-${{ matrix.slug }}
path: os/${{ matrix.slug }}/report.md
if-no-files-found: ignore