name: Test Actions (self-test) on: workflow_dispatch: {} workflow_run: workflows: - Build and Push Runner Images types: - completed push: branches: - main paths: - build-and-push/** - deploy-restart/** - kubectl-apply/** - ssh-deploy/** - .gitea/workflows/test-build.yaml - tests/** env: IMAGE: git.ivanch.me/ivanch/pipeline-actions-selftest jobs: test-build-push-amd64: name: AMD64 - Build tiny multi-arch image (${{ matrix.runner }}) if: ${{ gitea.event_name != 'workflow_run' || gitea.event.workflow_run.conclusion == 'success' }} runs-on: ${{ matrix.runner }} strategy: matrix: runner: [runner-slim-amd64, runner-full-amd64] steps: - name: Check out repository uses: actions/checkout@v4 - name: Generate a minimal Dockerfile shell: bash run: | mkdir -p _selftest cat > _selftest/Dockerfile <<'EOF' FROM alpine:3.20 RUN echo "pipeline-actions self-test build OK" CMD ["true"] EOF - name: Build and push via composite action uses: https://git.ivanch.me/ivanch/pipeline-actions/build-and-push@main with: image: ${{ env.IMAGE }} image_tag: citest build_context: _selftest build_dockerfile: Dockerfile registry_password: ${{ secrets.REGISTRY_PASSWORD }} ssh_key: ${{ secrets.SSH_KEY_DOCKERBUILD }} - name: Verify pushed image is pullable and multi-arch shell: bash env: IMAGE: ${{ env.IMAGE }} run: | echo "== inspecting ${IMAGE}:citest manifest ==" docker buildx imagetools inspect "${IMAGE}:citest" # Assert both target arches are present in the manifest list. MANIFEST="$(docker buildx imagetools inspect "${IMAGE}:citest")" echo "${MANIFEST}" | grep -q "linux/amd64" || { echo "missing linux/amd64"; exit 1; } echo "${MANIFEST}" | grep -q "linux/arm64" || { echo "missing linux/arm64"; exit 1; } echo "self-test PASSED: multi-arch image built and pushed" test-build-push-arm64: name: ARM64 - Build tiny multi-arch image (${{ matrix.runner }}) if: ${{ gitea.event_name != 'workflow_run' || gitea.event.workflow_run.conclusion == 'success' }} runs-on: ${{ matrix.runner }} strategy: matrix: runner: [runner-slim-arm64, runner-full-arm64] steps: - name: Check out repository uses: actions/checkout@v4 - name: Generate a minimal Dockerfile shell: bash run: | mkdir -p _selftest cat > _selftest/Dockerfile <<'EOF' FROM alpine:3.20 RUN echo "pipeline-actions self-test build OK" CMD ["true"] EOF - name: Build and push via composite action uses: https://git.ivanch.me/ivanch/pipeline-actions/build-and-push@main with: image: ${{ env.IMAGE }} image_tag: citest build_context: _selftest build_dockerfile: Dockerfile registry_password: ${{ secrets.REGISTRY_PASSWORD }} ssh_key: ${{ secrets.SSH_KEY_DOCKERBUILD }} - name: Verify pushed image is pullable and multi-arch shell: bash env: IMAGE: ${{ env.IMAGE }} run: | echo "== inspecting ${IMAGE}:citest manifest ==" docker buildx imagetools inspect "${IMAGE}:citest" # Assert both target arches are present in the manifest list. MANIFEST="$(docker buildx imagetools inspect "${IMAGE}:citest")" echo "${MANIFEST}" | grep -q "linux/amd64" || { echo "missing linux/amd64"; exit 1; } echo "${MANIFEST}" | grep -q "linux/arm64" || { echo "missing linux/arm64"; exit 1; } echo "self-test PASSED: multi-arch image built and pushed" test-k8s: name: Test Kubernetes actions (${{ matrix.runner }}) if: ${{ gitea.event_name != 'workflow_run' || gitea.event.workflow_run.conclusion == 'success' }} runs-on: ${{ matrix.runner }} strategy: matrix: runner: [runner-slim-amd64, runner-full-amd64, runner-slim-arm64, runner-full-arm64] env: TEST_NAMESPACE: pipeline-actions-test-${{ gitea.run_id }}-${{ matrix.runner }} steps: - name: Check out repository uses: actions/checkout@v4 - name: Create isolated test namespace shell: bash run: | printf '%s' "${{ secrets.KUBE_CONFIG }}" | tr -d '\r' > kubeconfig.yaml kubectl --kubeconfig=kubeconfig.yaml create namespace "${TEST_NAMESPACE}" - name: Apply test manifest uses: https://git.ivanch.me/ivanch/pipeline-actions/kubectl-apply@main with: kube_config: ${{ secrets.KUBE_CONFIG }} manifest: tests/manifests/test-deployment.yaml namespace: ${{ env.TEST_NAMESPACE }} - name: Restart test deployment uses: https://git.ivanch.me/ivanch/pipeline-actions/deploy-restart@main with: kube_config: ${{ secrets.KUBE_CONFIG }} deployment_name: pipeline-actions-test namespace: ${{ env.TEST_NAMESPACE }} - name: Verify deployment rollout status shell: bash run: | kubectl --kubeconfig=kubeconfig.yaml rollout status deployment/pipeline-actions-test -n "${TEST_NAMESPACE}" --timeout=60s - name: Clean up Kubernetes resources if: always() shell: bash run: | if [ ! -f kubeconfig.yaml ]; then printf '%s' "${{ secrets.KUBE_CONFIG }}" | tr -d '\r' > kubeconfig.yaml fi kubectl --kubeconfig=kubeconfig.yaml delete namespace "${TEST_NAMESPACE}" --ignore-not-found=true --wait=true --timeout=120s test-ssh: name: Test SSH deploy action (${{ matrix.runner }}) if: ${{ gitea.event_name != 'workflow_run' || gitea.event.workflow_run.conclusion == 'success' }} runs-on: ${{ matrix.runner }} strategy: matrix: runner: [runner-slim-amd64, runner-full-amd64, runner-slim-arm64, runner-full-arm64] env: TEST_ID: pipeline-actions-ssh-${{ gitea.run_id }}-${{ matrix.runner }} steps: - name: Check out repository uses: actions/checkout@v4 - name: Install and configure SSH server shell: bash run: | if [ "$(id -u)" -ne 0 ]; then echo "::error::The SSH self-test requires a root runner container." exit 1 fi if command -v apk >/dev/null 2>&1; then apk add --no-cache openssh-server elif command -v apt-get >/dev/null 2>&1; then export DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get install -y openssh-server else echo "::error::No supported package manager (apk or apt-get) was found." exit 1 fi mkdir -p /run/sshd ~/.ssh ssh-keygen -A rm -f ~/.ssh/id_test ~/.ssh/id_test.pub ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_test cat ~/.ssh/id_test.pub >> ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys "$(command -v sshd)" -p 2222 -o "ListenAddress 127.0.0.1" echo "SSH_USER=$(whoami)" >> "$GITHUB_ENV" echo "TEST_REMOTE_DIR=${HOME}/${TEST_ID}" >> "$GITHUB_ENV" echo "SSH_PRIVATE_KEY<> "$GITHUB_ENV" cat ~/.ssh/id_test >> "$GITHUB_ENV" echo "EOF" >> "$GITHUB_ENV" - name: Verify SSH localhost access shell: bash run: | ssh -p 2222 -i ~/.ssh/id_test -o StrictHostKeyChecking=accept-new "${SSH_USER}@127.0.0.1" "echo 'Localhost SSH OK'" - name: Set up remote compose directory and files shell: bash run: | mkdir -p "${TEST_REMOTE_DIR}" cat > "${TEST_REMOTE_DIR}/docker-compose.yml" <