Claude-code-plugins-plus oraclecloud-ci-integration
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/oraclecloud-pack/skills/oraclecloud-ci-integration" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-oraclecloud-ci-integration && rm -rf "$T"
plugins/saas-packs/oraclecloud-pack/skills/oraclecloud-ci-integration/SKILL.mdOracle Cloud CI Integration
Overview
Set up GitHub Actions workflows that authenticate to OCI, run Terraform plans, and execute tests against OCI services. The OCI Terraform provider has known bugs — notably ResourcePrincipal forcing the wrong region (#1761) — that require specific workarounds. This skill provides battle-tested CI patterns that avoid those pitfalls.
Purpose: Get a working CI pipeline that authenticates to OCI, runs Terraform safely, and tests OCI-dependent code without flaky failures.
Prerequisites
- OCI tenancy with an API signing key configured in
~/.oci/config - Terraform >= 1.5 and the OCI provider (
)oracle/oci - GitHub repository with Actions enabled
- GitHub Secrets configured:
,OCI_USER_OCID
,OCI_FINGERPRINT
,OCI_TENANCY_OCID
,OCI_REGION
(PEM contents, base64-encoded)OCI_PRIVATE_KEY - Python 3.8+ with
for SDK-based testspip install oci
Instructions
Step 1: Configure GitHub Secrets for OCI Auth
OCI API key authentication requires five values. Store them as GitHub repository secrets:
# Encode your private key for safe storage in GitHub Secrets base64 -w 0 ~/.oci/oci_api_key.pem # Copy output → GitHub Settings > Secrets > OCI_PRIVATE_KEY
The remaining secrets come from your
~/.oci/config file: user, fingerprint, tenancy, and region.
Step 2: GitHub Actions Workflow with Terraform
Create
.github/workflows/oci-terraform.yml:
name: OCI Terraform on: push: branches: [main] pull_request: env: TF_VAR_tenancy_ocid: ${{ secrets.OCI_TENANCY_OCID }} TF_VAR_user_ocid: ${{ secrets.OCI_USER_OCID }} TF_VAR_fingerprint: ${{ secrets.OCI_FINGERPRINT }} TF_VAR_region: ${{ secrets.OCI_REGION }} jobs: plan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Write OCI private key run: | echo "${{ secrets.OCI_PRIVATE_KEY }}" | base64 -d > /tmp/oci_key.pem chmod 600 /tmp/oci_key.pem - uses: hashicorp/setup-terraform@v3 with: terraform_version: "1.7.0" - name: Terraform Init run: terraform init - name: Terraform Plan run: terraform plan -out=tfplan env: TF_VAR_private_key_path: /tmp/oci_key.pem
Step 3: Terraform Provider Configuration
Configure the OCI provider with explicit region to avoid the ResourcePrincipal region bug (#1761):
terraform { required_providers { oci = { source = "oracle/oci" version = ">= 5.0.0" } } } provider "oci" { tenancy_ocid = var.tenancy_ocid user_ocid = var.user_ocid fingerprint = var.fingerprint private_key_path = var.private_key_path # CRITICAL: Always set region explicitly. # ResourcePrincipal auth can force the wrong region (#1761). region = var.region } variable "tenancy_ocid" {} variable "user_ocid" {} variable "fingerprint" {} variable "private_key_path" {} variable "region" { default = "us-ashburn-1" }
Step 4: OCI CLI Commands in CI
For non-Terraform CI tasks, use the OCI CLI directly:
- name: Install OCI CLI run: | pip install oci-cli mkdir -p ~/.oci echo "${{ secrets.OCI_PRIVATE_KEY }}" | base64 -d > ~/.oci/oci_api_key.pem chmod 600 ~/.oci/oci_api_key.pem cat > ~/.oci/config << EOF [DEFAULT] user=${{ secrets.OCI_USER_OCID }} fingerprint=${{ secrets.OCI_FINGERPRINT }} tenancy=${{ secrets.OCI_TENANCY_OCID }} region=${{ secrets.OCI_REGION }} key_file=~/.oci/oci_api_key.pem EOF - name: List compute instances run: oci compute instance list --compartment-id ${{ secrets.OCI_TENANCY_OCID }}
Step 5: Python SDK Tests with Mocks
Write testable OCI code by mocking the SDK clients:
import oci from unittest.mock import MagicMock, patch def list_instances(compartment_id: str) -> list: """List all compute instances in a compartment.""" config = oci.config.from_file("~/.oci/config") client = oci.core.ComputeClient(config) response = client.list_instances(compartment_id=compartment_id) return response.data @patch("oci.core.ComputeClient") @patch("oci.config.from_file") def test_list_instances(mock_config, mock_client_cls): mock_client = MagicMock() mock_client_cls.return_value = mock_client mock_client.list_instances.return_value.data = [ MagicMock(display_name="web-server-1", lifecycle_state="RUNNING") ] instances = list_instances("ocid1.compartment.oc1..example") assert len(instances) == 1 assert instances[0].display_name == "web-server-1"
Output
Successful completion produces:
- A GitHub Actions workflow that authenticates to OCI using API key secrets
- Terraform provider configuration with the explicit region workaround
- OCI CLI setup steps for non-Terraform CI tasks
- A test pattern using mocked OCI SDK clients for unit testing
Error Handling
| Error | Code | Cause | Solution |
|---|---|---|---|
| NotAuthenticated | 401 | Bad API key or wrong fingerprint | Verify secrets match values exactly |
| NotAuthorizedOrNotFound | 404 | IAM policy missing or wrong OCID | Add required IAM policy for the API key user |
| Provider crash on plan | N/A | ResourcePrincipal region bug (#1761) | Always set explicitly in provider block |
| TooManyRequests | 429 | Rate limited (no Retry-After header) | Add retry logic with exponential backoff |
| CERTIFICATE_VERIFY_FAILED | N/A | SSL cert issue in CI runner | Run and set |
| Terraform init fails | N/A | Provider version mismatch | Pin provider version: |
Examples
Quick OCI auth test in CI:
# Verify OCI credentials work in a GitHub Actions step pip install oci python3 -c " import oci config = oci.config.from_file('~/.oci/config') identity = oci.identity.IdentityClient(config) user = identity.get_user(config['user']).data print(f'Authenticated as: {user.name}') "
Terraform plan with JSON output for PR comments:
terraform plan -out=tfplan terraform show -json tfplan | python3 -c " import sys, json plan = json.load(sys.stdin) changes = plan.get('resource_changes', []) adds = sum(1 for c in changes if 'create' in c['change']['actions']) dels = sum(1 for c in changes if 'delete' in c['change']['actions']) print(f'Plan: +{adds} -{dels} resources') "
Resources
- OCI Terraform Provider — official provider documentation
- OCI API Reference — REST API specs for all services
- OCI Python SDK — SDK reference and examples
- OCI CLI Reference — command-line tool docs
- OCI SDK Troubleshooting — common error resolution
Next Steps
After CI is working, proceed to
oraclecloud-deploy-integration to set up container deployments via OKE or Container Instances, or see oraclecloud-observability to add monitoring to your CI-deployed infrastructure.