Skip to content

Commit

Permalink
Add reusable workflow to delete environment and revoke Salesforce token
Browse files Browse the repository at this point in the history
Add a new reusable workflow to delete an environment and revoke the Salesforce token.

* **New Workflow**: Add `delete-environment.yml` to `.github/workflows/` to delete an environment and revoke the Salesforce token.
  - Include steps to authenticate to DevHub, delete the environment, and revoke the Salesforce token using new d2x commands.
* **New Command**: Add `revoke_sf_token` function in `d2x/auth/sf/auth_url/__init__.py` to handle token revocation.
  - Implement the function to make API calls to Salesforce for token revocation.
  - Add necessary imports for the new function.
* **Documentation**: Update `README.md` to document the new workflow and command with usage instructions.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/muselab-d2x/d2x/tree/cumulusci-next-snapshots?shareId=XXXX-XXXX-XXXX-XXXX).
  • Loading branch information
jlantz committed Oct 31, 2024
1 parent 181d8ad commit c720b48
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 1 deletion.
59 changes: 59 additions & 0 deletions .github/workflows/delete-environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Delete Environment

on:
workflow_call:
inputs:
env-name:
required: true
type: string
sf-auth-url:
required: true
type: string
secrets:
dev-hub-auth-url:
required: true
github-token:
required: true

jobs:
delete-environment:
name: "Delete Environment"
runs-on: ubuntu-latest
container:
image: ghcr.io/muselab-d2x/d2x:cumulusci-next
options: --user root
credentials:
username: ${{ github.actor }}
password: ${{ secrets.github-token }}
env:
DEV_HUB_AUTH_URL: "${{ secrets.dev-hub-auth-url }}"
CUMULUSCI_SERVICE_github: '{ "username": "${{ github.actor }}", "token": "${{ secrets.github-token }}", "email": "NOTUSED" }'
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Auth to DevHub
run: /usr/local/bin/devhub.sh

- name: Delete Environment
run: cci org scratch_delete ${{ inputs.env-name }}
shell: bash

- name: Revoke Salesforce Token
run: |
python -c "
import os
from d2x.auth.sf.auth_url import revoke_sf_token
from rich.console import Console

console = Console()
sf_auth_url = os.environ.get('SF_AUTH_URL')
access_token = os.environ.get('ACCESS_TOKEN')
instance_url = os.environ.get('INSTANCE_URL')

revoke_sf_token(instance_url, access_token, console)
"
env:
SF_AUTH_URL: ${{ inputs.sf-auth-url }}
ACCESS_TOKEN: ${{ steps.auth_to_devhub.outputs.access_token }}
INSTANCE_URL: ${{ steps.auth_to_devhub.outputs.instance_url }}
103 changes: 102 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

D2X lets teams deliver repeatable, composable Salesforce products and solutions that align with Salesforce's [Well-Architected Framework](https://architect.salesforce.com/well-architected/overview).

D2X defines a container image for Salesforce development, build, and delivery using CumulusCI and Salesforce CLI. This gives teams a cconsistent runtime environment for automation used in across the entire software product lifecycle.
Expand All @@ -9,3 +8,105 @@ See [D2X documentation](https://d2x.readthedocs.io) for more details on using D2

Stay tuned for details on how to contribute!

## New Workflow: delete-environment.yml

A new reusable workflow `delete-environment.yml` has been added to delete an environment and revoke the Salesforce token. This workflow includes steps to authenticate to DevHub, delete the environment, and revoke the Salesforce token using new d2x commands.

### Usage Instructions

To use the `delete-environment.yml` workflow, follow these steps:

1. Create a new workflow file in your repository (e.g., `.github/workflows/delete-environment.yml`).
2. Copy the following content into the new workflow file:

```yaml
name: Delete Environment

on:
workflow_call:
inputs:
env-name:
required: true
type: string
sf-auth-url:
required: true
type: string
secrets:
dev-hub-auth-url:
required: true
github-token:
required: true

jobs:
delete-environment:
name: "Delete Environment"
runs-on: ubuntu-latest
container:
image: ghcr.io/muselab-d2x/d2x:cumulusci-next
options: --user root
credentials:
username: ${{ github.actor }}
password: ${{ secrets.github-token }}
env:
DEV_HUB_AUTH_URL: "${{ secrets.dev-hub-auth-url }}"
CUMULUSCI_SERVICE_github: '{ "username": "${{ github.actor }}", "token": "${{ secrets.github-token }}", "email": "NOTUSED" }'
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Auth to DevHub
run: /usr/local/bin/devhub.sh

- name: Delete Environment
run: cci org scratch_delete ${{ inputs.env-name }}
shell: bash

- name: Revoke Salesforce Token
run: |
python -c "
import os
from d2x.auth.sf.auth_url import revoke_sf_token
from rich.console import Console

console = Console()
sf_auth_url = os.environ.get('SF_AUTH_URL')
access_token = os.environ.get('ACCESS_TOKEN')
instance_url = os.environ.get('INSTANCE_URL')

revoke_sf_token(instance_url, access_token, console)
"
env:
SF_AUTH_URL: ${{ inputs.sf-auth-url }}
ACCESS_TOKEN: ${{ steps.auth_to_devhub.outputs.access_token }}
INSTANCE_URL: ${{ steps.auth_to_devhub.outputs.instance_url }}
```
3. Customize the workflow inputs and secrets as needed for your environment.
## New Command: revoke_sf_token
A new command `revoke_sf_token` has been added to the `d2x` library to handle token revocation by making appropriate API calls to Salesforce.
### Usage Instructions
To use the `revoke_sf_token` command, follow these steps:
1. Import the `revoke_sf_token` function from the `d2x.auth.sf.auth_url` module:
```python
from d2x.auth.sf.auth_url import revoke_sf_token
```
2. Call the `revoke_sf_token` function with the required parameters:
```python
from rich.console import Console
console = Console()
instance_url = "https://your-instance.salesforce.com"
access_token = "your-access-token"

revoke_sf_token(instance_url, access_token, console)
```

The `revoke_sf_token` function will make an API call to Salesforce to revoke the specified token and display the result in the console.
68 changes: 68 additions & 0 deletions d2x/auth/sf/auth_url/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,74 @@ def exchange_token(org_info: SalesforceOrgInfo, console: Console) -> TokenRespon
raise


def revoke_sf_token(instance_url: str, access_token: str, console: Console) -> None:
"""Revoke Salesforce token by making API call"""
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
console=console,
transient=True,
) as progress:
try:
progress.add_task("Preparing token revocation request...", total=None)

# Prepare the request
revoke_url_path = "/services/oauth2/revoke"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
body = urllib.parse.urlencode({"token": access_token})

# Make request
progress.add_task(f"Connecting to {instance_url}...", total=None)
conn = http.client.HTTPSConnection(instance_url)

task = progress.add_task("Revoking token...", total=None)
conn.request("POST", revoke_url_path, body, headers)
response = conn.getresponse()
response_data = response.read()

# Create response object
http_response = HttpResponse(
status=response.status,
reason=response.reason,
headers=dict(response.getheaders()),
body=response_data.decode("utf-8"),
)

if response.status != 200:
error_panel = Panel(
f"[red]HTTP Status: {http_response.status} {http_response.reason}\n\n"
f"[yellow]Response Headers:[/]\n"
f"{http_response.headers}\n\n"
f"[yellow]Response Body:[/]\n"
f"{http_response.body}",
title="[red]Token Revocation Failed",
border_style="red",
)
console.print(error_panel)
raise RuntimeError(
f"Token revocation failed: {response.status} {response.reason}"
)

progress.update(task, description="Token revocation successful!")

# Display success
success_panel = Panel(
f"[green]Successfully revoked token for {instance_url}",
title="[green]Token Revocation Success",
border_style="green",
)
console.print(success_panel)

except Exception as e:
error_panel = Panel(
f"[red]Error: {str(e)}",
title="[red]Token Revocation Failed",
border_style="red",
)
console.print(error_panel)
raise


def main():
console = Console(record=True)

Expand Down

0 comments on commit c720b48

Please sign in to comment.