Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright IBM Corp. 2025, 2026
# SPDX-License-Identifier: MPL-2.0

blank_issues_enabled: false
contact_links:
- name: HCP Terraform and Terraform Enterprise Troubleshooting and Feature Requests
Expand Down
51 changes: 51 additions & 0 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: SDK Integration Tests

on:
push:
workflow_dispatch:

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: make dev-install
- run: make fmt-check
- run: make lint
- run: make type-check && .venv/bin/python -m pytest -v tests/

integration-tests:
name: Integration Tests (Example Files)
runs-on: ubuntu-latest
needs: unit-tests

env:
TFE_TOKEN: ${{ secrets.TFE_TOKEN }}
TFE_ORG: ${{ secrets.TFE_ORG }}
TFE_ADDRESS: ${{ secrets.TFE_ADDRESS }}
TFE_WORKSPACE_ID: ${{ secrets.TFE_WORKSPACE_ID }}
TFE_WORKSPACE_NAME: ${{ secrets.TFE_WORKSPACE_NAME }}
TFE_RUN_ID: ${{ secrets.TFE_RUN_ID }}
TFE_APPLY_ID: ${{ secrets.TFE_APPLY_ID }}
TFE_PLAN_ID: ${{ secrets.TFE_PLAN_ID }}
TFE_TASK_STAGE_ID: ${{ secrets.TFE_TASK_STAGE_ID }}
TFE_POLICY_SET_ID: ${{ secrets.TFE_POLICY_SET_ID }}
TFE_POLICY_NAME: ${{ secrets.TFE_POLICY_NAME }}
TFE_REG_PROV_NS: ${{ secrets.TFE_REG_PROV_NS }}
TFE_REG_PROV_NAME: ${{ secrets.TFE_REG_PROV_NAME }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
OAUTH_CLIENT_GITHUB_TOKEN: ${{ secrets.OAUTH_CLIENT_GITHUB_TOKEN }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }}

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: make dev-install
- run: make test # ← single step, Makefile handles everything
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,4 @@ protos.bin

# Local RSA keys
.local/*

39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
# Unreleased

# v0.1.3

## Enhancements

### Iterator Pattern Migration
* Migrated Run resource list operations to iterator pattern by @NimishaShrivastava-dev [#91](https://github.com/hashicorp/python-tfe/pull/91)
* Migrated Policy resource list operations to iterator pattern by @TanyaSingh369-svg [#92](https://github.com/hashicorp/python-tfe/pull/92)
* Migrated Policy Set resource list operations to iterator pattern by @TanyaSingh369-svg [#95](https://github.com/hashicorp/python-tfe/pull/95)
* Migrated Run Event resource list operations to iterator pattern by @NimishaShrivastava-dev [#97](https://github.com/hashicorp/python-tfe/pull/97)
* Migrated SSH Keys resource list operations to iterator pattern by @NimishaShrivastava-dev [#101](https://github.com/hashicorp/python-tfe/pull/101)
* Migrated Notification Configuration resource list operations to iterator pattern by @TanyaSingh369-svg [#109](https://github.com/hashicorp/python-tfe/pull/109)
* Migrated Variable Set list operations to iterator pattern by @isivaselvan [#113](https://github.com/hashicorp/python-tfe/pull/113)
* Migrated Variable Set Variables list operations to iterator pattern by @isivaselvan [#113](https://github.com/hashicorp/python-tfe/pull/113)
* Migrated State Version list operations to iterator pattern by @isivaselvan [#113](https://github.com/hashicorp/python-tfe/pull/113)
* Migrated State Version Output list operations to iterator pattern by @isivaselvan [#113](https://github.com/hashicorp/python-tfe/pull/113)
* Migrated Policy Check list operations to iterator pattern by @isivaselvan [#113](https://github.com/hashicorp/python-tfe/pull/113)
* Refreshed examples and unit tests to align with iterator pattern updates by @NimishaShrivastava-dev, @TanyaSingh369-svg, @isivaselvan [#91](https://github.com/hashicorp/python-tfe/pull/91) [#92](https://github.com/hashicorp/python-tfe/pull/92) [#95](https://github.com/hashicorp/python-tfe/pull/95) [#97](https://github.com/hashicorp/python-tfe/pull/97) [#101](https://github.com/hashicorp/python-tfe/pull/101) [#109](https://github.com/hashicorp/python-tfe/pull/109) [#113](https://github.com/hashicorp/python-tfe/pull/113)

### Project and Workspace Management
* Updated Project create and update models, including Project model refinements by @isivaselvan [#120](https://github.com/hashicorp/python-tfe/pull/120)
* Updated Project endpoints for list-effective-tag-bindings and delete-tag-bindings by @isivaselvan [#120](https://github.com/hashicorp/python-tfe/pull/120)
* Refactored Workspace models to improve validation with Pydantic by @isivaselvan [#106](https://github.com/hashicorp/python-tfe/pull/106)

## Breaking Change

### List Method Behavior
* Standardized list methods across multiple resources to iterator-based behavior, replacing legacy list response patterns by @NimishaShrivastava-dev, @TanyaSingh369-svg, @isivaselvan [#91](https://github.com/hashicorp/python-tfe/pull/91) [#92](https://github.com/hashicorp/python-tfe/pull/92) [#95](https://github.com/hashicorp/python-tfe/pull/95) [#97](https://github.com/hashicorp/python-tfe/pull/97) [#101](https://github.com/hashicorp/python-tfe/pull/101) [#109](https://github.com/hashicorp/python-tfe/pull/109) [#113](https://github.com/hashicorp/python-tfe/pull/113)

## Bug Fixes
* Fixed pagination parameter handling across iterator-based page traversal by @isivaselvan [#111](https://github.com/hashicorp/python-tfe/pull/111)
* Fixed state version and state version output model import/export registration by @isivaselvan [#105](https://github.com/hashicorp/python-tfe/pull/105)
* Fixed the tag based filtering of workspace in list operation by @isivaselvan [#106](https://github.com/hashicorp/python-tfe/pull/106)
* Fixed the project response of workspace relationship by @isivaselvan [#106](https://github.com/hashicorp/python-tfe/pull/106)
* Fixed configuration version examples and added terraform+cloud support for ConfigurationSource usage by @isivaselvan [#107](https://github.com/hashicorp/python-tfe/pull/107)
* Fixed configuration upload packaging flow (tarfile-based handling) by @isivaselvan [#107](https://github.com/hashicorp/python-tfe/pull/107)
* Updated agent pool workspace assign/remove operations to consistently return AgentPool objects by @KshitijaChoudhari [#110](https://github.com/hashicorp/python-tfe/pull/110)
* Updated Run relationships handling for improved model consistency by @ibm-richard [#119](https://github.com/hashicorp/python-tfe/pull/119)
* Updated additional Run Source attributes by @isivaselvan [#123](https://github.com/hashicorp/python-tfe/pull/123)

# v0.1.2

## Features
Expand Down
264 changes: 251 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,42 @@ VENV_PIP := $(VENV)/bin/pip

help:
@echo "Available targets:"
@echo " venv Create virtual environment"
@echo " activate Show command to activate virtual environment"
@echo " install Install package dependencies"
@echo " dev-install Install package and development dependencies"
@echo " fmt Format code"
@echo " fmt-check Check code formatting"
@echo " lint Run linting"
@echo " check Run format check + lint + type check"
@echo " type-check Run type checking"
@echo " test Run unit tests"
@echo " clean Clean build artifacts and cache"
@echo " all Run clean + dev-install + fmt + lint + test"
@echo " venv Create virtual environment"
@echo " activate Show command to activate virtual environment"
@echo " install Install package dependencies"
@echo " dev-install Install package and development dependencies"
@echo " fmt Format code"
@echo " fmt-check Check code formatting"
@echo " lint Run linting"
@echo " check Run format check + lint + type check"
@echo " type-check Run type checking"
@echo " test Run unit tests + all example files"
@echo " clean Clean build artifacts and cache"
@echo " all Run clean + dev-install + fmt + lint + test"
@echo ""
@echo "Required env vars:"
@echo " TFE_TOKEN API token"
@echo " TFE_ORG Organization name"
@echo ""
@echo "Optional env vars (examples skip cleanly if not set):"
@echo " TFE_ADDRESS TFE address (default: https://app.terraform.io)"
@echo " TFE_WORKSPACE_ID Workspace ID"
@echo " -- needed by: configuration_version, notification_configuration,"
@echo " variables, workspace_resources, state_versions"
@echo " TFE_WORKSPACE_NAME Workspace name"
@echo " -- needed by: notification_configuration, state_versions"
@echo " TFE_APPLY_ID Apply ID -- needed by: apply"
@echo " TFE_PLAN_ID Plan ID -- needed by: plan"
@echo " TFE_RUN_ID Run ID -- needed by: policy_check, run_events"
@echo " TFE_TASK_STAGE_ID Task stage ID -- needed by: policy_evaluation"
@echo " TFE_POLICY_SET_ID Policy set ID -- needed by: policy_set_parameter"
@echo " TFE_POLICY_NAME Policy name -- needed by: policy"
@echo " TFE_REG_PROV_NS Registry provider namespace -- needed by: registry_provider_version"
@echo " TFE_REG_PROV_NAME Registry provider name -- needed by: registry_provider_version"
@echo " SSH_PRIVATE_KEY SSH private key -- needed by: ssh_keys"
@echo " OAUTH_CLIENT_GITHUB_TOKEN GitHub token (optional, enables GitHub tests in oauth_client)"
@echo " WEBHOOK_URL Webhook URL -- used by: notification_configuration"
@echo " TEAMS_WEBHOOK_URL Teams URL -- used by: notification_configuration"

$(VENV)/bin/activate: pyproject.toml
$(PYTHON) -m venv $(VENV)
Expand Down Expand Up @@ -59,7 +83,220 @@ type-check:
$(VENV_PYTHON) -m mypy $(SRC_DIR)

test:
$(VENV_PYTHON) -m pytest -v
@echo "Checking required environment variables..."
@if [ -z "$${TFE_TOKEN}" ] || [ -z "$${TFE_ORG}" ]; then \
echo "ERROR: TFE_TOKEN and TFE_ORG must be set"; \
exit 1; \
fi

@echo ""
@echo "========================================"
@echo "Running unit tests..."
@echo "========================================"
$(VENV_PYTHON) -m pytest -v tests/

@echo ""
@echo "========================================"
@echo "Running example files..."
@echo "========================================"

@echo ""
@echo "--- agent.py ---"
-$(VENV_PYTHON) examples/agent.py

@echo ""
@echo "--- agent_pool.py ---"
-$(VENV_PYTHON) examples/agent_pool.py

@echo ""
@echo "--- apply.py ---"
@if [ -z "$${TFE_APPLY_ID}" ]; then \
echo "SKIPPED: set TFE_APPLY_ID to run apply.py"; \
else \
$(VENV_PYTHON) examples/apply.py --apply-id "$${TFE_APPLY_ID}" || true; \
fi

@echo ""
@echo "--- configuration_version.py ---"
@if [ -z "$${TFE_WORKSPACE_ID}" ]; then \
echo "SKIPPED: set TFE_WORKSPACE_ID to run configuration_version.py"; \
else \
$(VENV_PYTHON) examples/configuration_version.py || true; \
fi

@echo ""
@echo "--- notification_configuration.py ---"
@if [ -z "$${TFE_WORKSPACE_ID}" ] && [ -z "$${TFE_WORKSPACE_NAME}" ]; then \
echo "SKIPPED: set TFE_WORKSPACE_ID or TFE_WORKSPACE_NAME to run notification_configuration.py"; \
else \
$(VENV_PYTHON) examples/notification_configuration.py || true; \
fi

@echo ""
@echo "--- oauth_client.py ---"
-$(VENV_PYTHON) examples/oauth_client.py

@echo ""
@echo "--- oauth_token.py ---"
-$(VENV_PYTHON) examples/oauth_token.py

@echo ""
@echo "--- org.py ---"
-$(VENV_PYTHON) examples/org.py

@echo ""
@echo "--- organization_membership.py ---"
-$(VENV_PYTHON) examples/organization_membership.py

@echo ""
@echo "--- plan.py ---"
@if [ -z "$${TFE_PLAN_ID}" ]; then \
echo "SKIPPED: set TFE_PLAN_ID to run plan.py"; \
else \
$(VENV_PYTHON) examples/plan.py --plan-id "$${TFE_PLAN_ID}" || true; \
fi

@echo ""
@echo "--- policy_check.py ---"
@if [ -z "$${TFE_RUN_ID}" ]; then \
echo "SKIPPED: set TFE_RUN_ID to run policy_check.py"; \
else \
$(VENV_PYTHON) examples/policy_check.py --run-id "$${TFE_RUN_ID}" || true; \
fi

@echo ""
@echo "--- policy_evaluation.py ---"
@if [ -z "$${TFE_TASK_STAGE_ID}" ]; then \
echo "SKIPPED: set TFE_TASK_STAGE_ID to run policy_evaluation.py"; \
else \
$(VENV_PYTHON) examples/policy_evaluation.py \
--task-stage-id "$${TFE_TASK_STAGE_ID}" || true; \
fi

@echo ""
@echo "--- policy_set_parameter.py ---"
@if [ -z "$${TFE_POLICY_SET_ID}" ]; then \
echo "SKIPPED: set TFE_POLICY_SET_ID to run policy_set_parameter.py"; \
else \
$(VENV_PYTHON) examples/policy_set_parameter.py \
--policy-set-id "$${TFE_POLICY_SET_ID}" || true; \
fi

@echo ""
@echo "--- policy_set.py ---"
-$(VENV_PYTHON) examples/policy_set.py --org "$${TFE_ORG}"

@echo ""
@echo "--- policy.py ---"
@if [ -z "$${TFE_POLICY_NAME}" ]; then \
echo "SKIPPED: set TFE_POLICY_NAME to run policy.py"; \
else \
$(VENV_PYTHON) examples/policy.py \
--org "$${TFE_ORG}" \
--policy-name "$${TFE_POLICY_NAME}" || true; \
fi

@echo ""
@echo "--- project.py ---"
-$(VENV_PYTHON) examples/project.py --list --organization "$${TFE_ORG}"

@echo ""
@echo "--- query_run.py ---"
-$(VENV_PYTHON) examples/query_run.py

@echo ""
@echo "--- registry_module.py ---"
-$(VENV_PYTHON) examples/registry_module.py

@echo ""
@echo "--- registry_provider_version.py ---"
@if [ -z "$${TFE_REG_PROV_NS}" ] || [ -z "$${TFE_REG_PROV_NAME}" ]; then \
echo "SKIPPED: set TFE_REG_PROV_NS and TFE_REG_PROV_NAME to run registry_provider_version.py"; \
else \
$(VENV_PYTHON) examples/registry_provider_version.py \
--organization "$${TFE_ORG}" \
--namespace "$${TFE_REG_PROV_NS}" \
--name "$${TFE_REG_PROV_NAME}" || true; \
fi

@echo ""
@echo "--- registry_provider.py ---"
-$(VENV_PYTHON) examples/registry_provider.py

@echo ""
@echo "--- reserved_tag_key.py ---"
-$(VENV_PYTHON) examples/reserved_tag_key.py

@echo ""
@echo "--- run_events.py ---"
@if [ -z "$${TFE_RUN_ID}" ]; then \
echo "SKIPPED: set TFE_RUN_ID to run run_events.py"; \
else \
$(VENV_PYTHON) examples/run_events.py --run-id "$${TFE_RUN_ID}" || true; \
fi

@echo ""
@echo "--- run_task.py ---"
-$(VENV_PYTHON) examples/run_task.py --org "$${TFE_ORG}"

@echo ""
@echo "--- run_trigger.py ---"
-$(VENV_PYTHON) examples/run_trigger.py --org "$${TFE_ORG}"

@echo ""
@echo "--- run.py ---"
-$(VENV_PYTHON) examples/run.py --organization "$${TFE_ORG}"

@echo ""
@echo "--- ssh_keys.py ---"
@if [ -z "$${SSH_PRIVATE_KEY}" ]; then \
echo "SKIPPED: set SSH_PRIVATE_KEY to run ssh_keys.py"; \
else \
$(VENV_PYTHON) examples/ssh_keys.py || true; \
fi

@echo ""
@echo "--- state_versions.py ---"
@if [ -z "$${TFE_WORKSPACE_ID}" ] || [ -z "$${TFE_WORKSPACE_NAME}" ]; then \
echo "SKIPPED: set TFE_WORKSPACE_ID and TFE_WORKSPACE_NAME to run state_versions.py"; \
else \
$(VENV_PYTHON) examples/state_versions.py \
--org "$${TFE_ORG}" \
--workspace "$${TFE_WORKSPACE_NAME}" \
--workspace-id "$${TFE_WORKSPACE_ID}" || true; \
fi

@echo ""
@echo "--- variable_sets.py ---"
-$(VENV_PYTHON) examples/variable_sets.py

@echo ""
@echo "--- variables.py ---"
@if [ -z "$${TFE_WORKSPACE_ID}" ]; then \
echo "SKIPPED: set TFE_WORKSPACE_ID to run variables.py"; \
else \
$(VENV_PYTHON) examples/variables.py || true; \
fi

@echo ""
@echo "--- workspace_resources.py ---"
@if [ -z "$${TFE_WORKSPACE_ID}" ]; then \
echo "SKIPPED: set TFE_WORKSPACE_ID to run workspace_resources.py"; \
else \
$(VENV_PYTHON) examples/workspace_resources.py \
--list \
--workspace-id "$${TFE_WORKSPACE_ID}" \
--page-size 10 || true; \
fi

@echo ""
@echo "--- workspace.py ---"
-$(VENV_PYTHON) examples/workspace.py --org "$${TFE_ORG}" --list

@echo ""
@echo "========================================"
@echo "All examples completed."
@echo "========================================"

clean:
find . -type f -name "*.pyc" -delete
Expand All @@ -71,3 +308,4 @@ clean:
rm -rf build/ dist/ $(VENV)

all: clean dev-install fmt lint test

3 changes: 3 additions & 0 deletions bin/publish-pypi.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2025, 2026
# SPDX-License-Identifier: MPL-2.0

set -euo pipefail


Expand Down
Loading
Loading