Hi hi, wondering if anyone can point me in the rig...
# pulumi-deployments
d
Hi hi, wondering if anyone can point me in the right direction here… I’m using Pulumi Deployments I’ve configured with Pulumi itself: `pulumiservice.DeploymentSettings`:
Copy code
def deployment_settings(project: str, stack: str, repo_dir: str):
    return pulumiservice.DeploymentSettings(
        resource_name=f"Deployment Settings: {project}/{stack}",
        executor_context=pulumiservice.DeploymentSettingsExecutorContextArgs(
            executor_image="<http://ghcr.io/my-github-org/pulumi-deployments-executor:latest|ghcr.io/my-github-org/pulumi-deployments-executor:latest>",
        ),
        github=pulumiservice.DeploymentSettingsGithubArgs(
            deploy_commits=True,
            preview_pull_requests=True,
            repository="my-github-org/infrastructure",
            paths=[f"{repo_dir}/**"],  # Limit auto-deploy to the specified directory
        ),
        operation_context=pulumiservice.DeploymentSettingsOperationContextArgs(
            oidc=pulumiservice.OperationContextOIDCArgs(
                aws=pulumiservice.AWSOIDCConfigurationArgs(
                    duration="45m0s",
                    role_arn="arn:aws:iam::MY-ACCOUNT:role/PulumiOIDC",
                    session_name="pulumi",
                ),
            ),
            options=pulumiservice.OperationContextOptionsArgs(
                skip_install_dependencies=True,
            ),
            pre_run_commands=["prerun.sh"],
        ),
        organization="mighty",
        project=project,
        stack=stack,
        source_context=pulumiservice.DeploymentSettingsSourceContextArgs(
            git=pulumiservice.DeploymentSettingsGitSourceArgs(
                branch="refs/heads/main",
                repo_dir=repo_dir,
            ),
        ),
    )
This allows me to deploy either from the UI via the button and automatically happens during PRs to my infra repo. I’m now working on something else where I want to use the Automation API to trigger a deployment of a different stack not otherwise set up for Deployments. Looking to do something like: https://github.com/pulumi/automation-api-examples/blob/main/python/remote_deployment/main.py However I’m running into trouble with GitHub authentication. Says
failed to clone repo:: failed to create workspace, unable to enlist in git repo: unable to clone repo: authentication required; retrying
I’m curious if there’s a better way to do this. Is there a way to create a deployment configuration and trigger that?
Does it make more sense to set up a Deployment using my
deployment_settings
above and then trigger it via the REST API as such:
Copy code
import os
import requests

PULUMI_API_URL = "<https://api.pulumi.com/api/preview/organizations/{org}/projects/{project}/stacks/{stack}/deployments>"
PULUMI_ACCESS_TOKEN = os.getenv("PULUMI_ACCESS_TOKEN")

def trigger_pulumi_deployment_with_env(org, project, stack, custom_env):
    url = PULUMI_API_URL.format(org=org, project=project, stack=stack)
    headers = {
        "Authorization": f"token {PULUMI_ACCESS_TOKEN}",
        "Content-Type": "application/json"
    }
    payload = {
        "operation": "update",  # Could also be "destroy"
        "environmentVariables": custom_env
    }

    response = <http://requests.post|requests.post>(url, headers=headers, json=payload)
    if response.status_code == 201:
        print("Deployment triggered successfully!")
    else:
        print(f"Failed to trigger deployment: {response.status_code}")
        print(response.json())

# Example usage
org = "your-org-name"
project = "your-project-name"
stack = "your-stack-name"
custom_env = {
    "CUSTOM_ENV_VAR": "custom-value",
    "ANOTHER_ENV_VAR": "another-value"
}
trigger_pulumi_deployment_with_env(org, project, stack, custom_env)
I was able to figure out how to generate a github token and pass it via the
auth=
param:
Copy code
github_token = get_installation_token(GITHUB_APP_ID, GITHUB_INSTALLATION_ID)

    stack = auto.create_or_select_remote_stack_git_source(
        stack_name=stack_name,
        url=REPO,
        branch=BRANCH,
        project_path=project,
        opts=auto.RemoteWorkspaceOptions(
            env_vars={
                "AWS_REGION": os.environ["AWS_REGION"],
                "AWS_ACCESS_KEY_ID": os.environ["AWS_ACCESS_KEY_ID"],
                "AWS_SECRET_ACCESS_KEY": auto.Secret(os.environ["AWS_SECRET_ACCESS_KEY"]),
                "AWS_SESSION_TOKEN": auto.Secret(os.environ["AWS_SESSION_TOKEN"]),
            },
        ),
        auth=auto.RemoteGitAuth(
            personal_access_token=github_token,
        ),
    )
Now I have a question… in my
DeploymentSettings
I have a custom executor image selected. Is there a way to do that in the automation api’s
create_or_select_remote_stack_git_source
?
h
it looks like at least the go automation sdk supports this, but I don't see a similar option for the python sdk. you might still be able to get it to work by creating deployment settings on the stack w/ the executor image config set, and then using the inherit_settings option on your
create_or_select_remote_stack_git_source
call, which I believe will cause the remote deployment to inherit non-overridden deployment settings for the stack.
d
ahh interesting… I’m thinking to instead use the Automation API to create a stack and then use the Deployments REST API to create a deployment
h
yeah I think that's probably a more straightforward approach!
d
Do you know if there’s any way to set a config value in the stack via the Deployment REST API? Seems like you can only set ENV variables that will be available to the deployment exectuor?
r
o you know if there’s any way to set a config value in the stack via the Deployment REST API? Seems like you can only set ENV variables that will be available to the deployment exectuor?
You can set config in pre-run commands by doing
pulumi config set ...
d
Ahh, so add another command in the
preRunCommands
list?
Copy code
def trigger_pulumi_deployment(
    org: str,
    project: str,
    stack: str,
    operation: Literal["preview", "update", "destroy"],
    repo_dir: str,
    branch: str,
    custom_env: Optional[dict[str, str]] = None,
):
    url = PULUMI_API_URL.format(org=org, project=project, stack=stack)
    headers = {"Authorization": f"token {PULUMI_ACCESS_TOKEN}", "Content-Type": "application/json"}
    payload = {
        "inheritSettings": False,  # Deploy fresh settings
        "operation": operation,
        "executorContext": {
            "executorImage": EXECUTOR_IMAGE,
        },
        "github": {
            "repository": REPOSITORY,
            "deployCommits": False,
            "previewPullRequests": False,
            "pullRequestTemplate": False,
            # "paths": [],  # not needed as we do not want auto-deployments
        },
        "operationContext": {
            "oidc": {
                "aws": {
                    "duration": OIDC_DURATION,
                    "roleArn": OIDC_ROLE_ARN,
                    "sessionName": OIDC_SESSION_NAME,
                },
            },
            "options": {
                "skipInstallDependencies": True,
            },
            "preRunCommands": ["prerun.sh"],
        },
        "sourceContext": {
            "git": {
                "branch": f"refs/heads/{branch}",
                "repoDir": repo_dir,
            },
        },
    }
    if custom_env:
        payload["operationContext"]["environmentVariables"] = custom_env

    response = <http://requests.post|requests.post>(url, headers=headers, json=payload)
I did work around it by setting
environmentVariables
and then fetching the value in my stack via:
version = os.environ["APP_REVISION"]
. I am wondering about how to think about stack config vs. passing a value like this at runtime