This repository includes a GitHub Actions workflow for post-publish sanity-testing AlmaLinux OS Compute Custom Images on Oracle Cloud Infrastructure. The workflow launches a fresh test instance from a given Compute Image OCID, runs a small set of release / arch / disk / dnf assertions over SSH, terminates the instance on always(), and posts a Mattermost summary.
It is the OCI counterpart of AZURE_TEST.md.
Workflow for validating an OCI Compute Custom Image end-to-end.
What it does:
- Accepts an
image_ocid(e.g.ocid1.image.oc1..<unique_id>) - Reads the image
display-nameand parses it for AlmaLinux major/version/datestamp/architecture - Maps architecture to an OCI shape (
x86_64→VM.Standard.E5.Flex,aarch64→VM.Standard.A1.Flex) - Generates an ephemeral ed25519 SSH keypair, launches a test instance with a public IP, waits for SSH, runs the assertions, then terminates the instance
- Sends a Mattermost notification with OCI Console links to the image and the (now-terminated) test instance
The installed-packages list is not collected here: the build workflow already stores it as a workflow artifact from its offline (qemu-nbd) test stage.
Usage:
Trigger via GitHub UI: Actions → OCI: Test Image
Inputs:
- image_ocid: Compute Image OCID (must start with ocid1.image.)
- notify_mattermost: Send notification to Mattermost (default: true)
The release workflow oci-marketplace-publish.yml creates the Compute Custom Image whose OCID this workflow consumes.
| Secret | Description |
|---|---|
OCI_CLI_USER |
OCI user OCID |
OCI_CLI_TENANCY |
OCI tenancy OCID |
OCI_CLI_FINGERPRINT |
API key fingerprint |
OCI_CLI_KEY_CONTENT |
Private API key content (PEM) |
OCI_COMPARTMENT_ID |
Compartment OCID for the test instance |
OCI_SUBNET_ID |
Public subnet OCID in OCI_CLI_REGION |
MATTERMOST_WEBHOOK_URL |
Mattermost incoming webhook URL |
| Variable | Description |
|---|---|
OCI_CLI_REGION |
OCI region (e.g. us-ashburn-1) |
MATTERMOST_CHANNEL |
Mattermost channel for notifications |
| Env | Value |
|---|---|
OCI_COMPUTE_BASE_URL |
https://cloud.oracle.com/compute |
SSH_USER (job-level) |
opc |
The Compute Image's display-name is parsed against a strict regex:
^AlmaLinux-(<major>)-OCI-(<version>)-(<datestamp>[.<iter>])\.(x86_64|aarch64)$
| Component | Example |
|---|---|
ALMA_MAJOR |
10 |
ALMA_VERSION |
10.1 |
ALMA_DATE |
20260502.0 |
ALMA_ARCH |
x86_64 or aarch64 |
RELEASE_STRING |
AlmaLinux release <ALMA_VERSION> |
Display names that do not match this pattern fail the workflow at the parse step before any OCI resources are touched.
| Architecture | Shape | Config |
|---|---|---|
x86_64 |
VM.Standard.E5.Flex |
2 OCPU / 8 GiB |
aarch64 |
VM.Standard.A1.Flex |
2 OCPU / 8 GiB |
Boot volume is set to 100 GiB so the root-filesystem-resize assertion (≥ 98 GiB) has headroom.
Once SSH is reachable on the test instance, the following checks run in sequence (failure of any aborts the workflow):
- AlmaLinux release —
grep '<RELEASE_STRING>' /etc/almalinux-release - System architecture —
rpm -q --qf='%{ARCH}\n' almalinux-release | grep '<ALMA_ARCH>' - OCI-specific packages —
rpm -q cloud-init nvme-cli iscsi-initiator-utils iscsi-initiator-utils-iscsiuio device-mapper-multipath.cloud-initis OCI's instance provisioning agent (datasource at/etc/cloud/cloud.cfg.d/99_oci.cfg); the rest are NVMe / iSCSI / multipath support installed byansible/roles/oci_guest/tasks/main.yaml.rpm -qexits non-zero if any package is missing - Disk and filesystems —
lsblklisting - Root filesystem resize — root must be ≥ 98 GiB (the boot-volume-size-in-gbs is 100 GiB)
- Updates available —
sudo dnf check-update(exit code100is treated as success — it just means updates are pending)
graph TD
A[Trigger Workflow] --> V[Validate image_ocid]
V --> I[Install OCI CLI + dependencies]
I --> CFG[Configure OCI CLI — write key.pem]
CFG --> P[Read image metadata + parse display-name]
P --> K[Generate ephemeral SSH keypair — ed25519]
K --> AD[Resolve availability domain]
AD --> L[Launch test instance — oci compute instance launch]
L --> IP[Resolve instance public IP via VNIC]
IP --> W[Wait for SSH — 60 × 10 s nc]
W --> T[Run image tests — release/arch/disk/dnf]
T --> S[Job summary — OCI Console links]
S --> CL[Terminate test instance — wait for TERMINATED]
CL --> N[Send Mattermost notification]
The test instance is named oci-test-${ALMA_VERSION}-${ALMA_DATE}-${ALMA_ARCH}-${GITHUB_RUN_ID} (GITHUB_RUN_ID keeps concurrent dispatches collision-free).
The Terminate test instance step runs under if: always() && env.INSTANCE_OCID != '':
oci compute instance terminate \
--instance-id "${INSTANCE_OCID}" \
--force \
--wait-for-state TERMINATEDOCI's terminate deletes the instance, the boot volume (because we created it inline rather than from a separate volume), and the auto-attached VNIC, so no per-resource cleanup is needed.
-
First dispatch against an x86_64 image:
- Use the OCID of a recently imported AlmaLinux 10 OCI image
- Confirm green run and Mattermost summary
-
aarch64 dispatch:
- Same flow with an aarch64 OCID — confirms the
VM.Standard.A1.Flexshape path
- Same flow with an aarch64 OCID — confirms the
-
Cleanup verification:
- After the run, search instances in the compartment for the run ID:
Expected:
oci compute instance list \ --compartment-id "$OCI_COMPARTMENT_ID" \ --query "data[?contains(\"display-name\", '<run_id>')]"
[](or the instance inTERMINATEDstate).
- After the run, search instances in the compartment for the run ID:
-
"Invalid Compute Image OCID"
- The OCID must start with
ocid1.image.. Other OCID types (ocid1.compute-image-version,ocid1.marketplacepublisherartifact, etc.) are rejected at the validate step.
- The OCID must start with
-
"Unexpected Custom Image Name"
- The image's
display-namedid not match theAlmaLinux-<major>-OCI-<version>-<datestamp>[.<iter>].<arch>pattern. Confirm the image was imported viaoci-marketplace-publish.yml, which sets the canonical display name.
- The image's
-
Instance launch fails with capacity / quota error
- Pick a different shape config (edit the workflow) or wait and re-run. AlmaLinux 10 ARM is in
VM.Standard.A1.Flexquota which is per-tenancy.
- Pick a different shape config (edit the workflow) or wait and re-run. AlmaLinux 10 ARM is in
-
"Instance has no public IP"
- The subnet specified in
OCI_SUBNET_IDis private. The workflow needs a public subnet because it SSH's from the GitHub-hosted runner.
- The subnet specified in
-
"SSH did not become reachable within 10 minutes"
- The instance came up but SSH never opened on port 22 from the runner. Possible causes: stateful ingress rule on the subnet's security list / NSG missing for port 22, cloud-init still bringing up
sshd, oropcuser not yet provisioned (cloud-init drift).
- The instance came up but SSH never opened on port 22 from the runner. Possible causes: stateful ingress rule on the subnet's security list / NSG missing for port 22, cloud-init still bringing up
-
"Root filesystem resize check failed"
- The root filesystem on the test instance did not auto-grow to ≥ 98 GiB. Indicates a
cloud-init/growpartregression in the imported image.
- The root filesystem on the test instance did not auto-grow to ≥ 98 GiB. Indicates a
-
package X is not installed(from the OCI-specific packages assertion)- The image is missing one of
cloud-init,nvme-cli,iscsi-initiator-utils,iscsi-initiator-utils-iscsiuio, ordevice-mapper-multipath. Indicates theoci_guest/setup_cloud_initAnsible roles did not run (or partially failed) during the image build. Re-build the OCI image and verify the Packer log shows both roles applied without errors.
- The image is missing one of
-
dnf check-updateexits with non-100, non-0 code- Repo metadata fetch failure or signed metadata mismatch. Re-run; if persistent, check that the image's repo data is current.
-
"Termination" step times out
- OCI is occasionally slow to fully terminate an instance. The workflow runs
--wait-for-state TERMINATED, so failure here means OCI did not converge — inspect the instance in the OCI Console manually.
- OCI is occasionally slow to fully terminate an instance. The workflow runs
GitHub Actions YAML linters may show "Context access might be invalid" warnings for environment variables set via $GITHUB_ENV. These are false positives — the workflow functions correctly.
- OCI Console: https://cloud.oracle.com/compute
- OCI Compute Custom Images docs: https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/managingcustomimages.htm
- AlmaLinux Cloud SIG Chat: https://chat.almalinux.org/almalinux/channels/sigcloud
- Workflow run logs: GitHub Actions tab in the repository