Skip to content

Commit 3d8ef19

Browse files
added CI/CD workflow
1 parent 02a654f commit 3d8ef19

11 files changed

Lines changed: 172 additions & 96 deletions

File tree

.github/workflows/python.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3+
4+
name: Python CI
5+
6+
on:
7+
push:
8+
branches: [ "master" ]
9+
pull_request:
10+
branches: [ "master" ]
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
build:
17+
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v3
22+
- name: Set up Python 3.10
23+
uses: actions/setup-python@v3
24+
with:
25+
python-version: "3.10"
26+
27+
- name: Install dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install flake8 pytest
31+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
32+
33+
- name: Lint with flake8
34+
run: flake8
35+
36+
- name: Write private key
37+
run: |
38+
echo '${{ secrets.PRIVATE_KEY }}' >> app/private.key
39+
40+
- name: Test with pytest
41+
run: pytest
42+
env:
43+
CLIENT_ID: '${{ secrets.CLIENT_ID }}'
44+
USER_ID: '${{ secrets.USER_ID }}'
45+
SIGNER_EMAIL: '${{ secrets.SIGNER_EMAIL }}'
46+
SIGNER_NAME: '${{ secrets.SIGNER_NAME }}'

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
app/ds_config*
1+
app/.env
22

33
*/.DS_Store
44
.DS_Store

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,31 +88,31 @@ For a list of code examples that use the Admin API, see the [How-to guides overv
8888
1. In your command-line environment, switch to the folder:
8989
`cd <Quickstart folder>` or `cd code-examples-python`
9090
1. To install dependencies, run: `pip3 install -r requirements.txt` (or pipenv can be used)
91-
1. To configure the launcher for [Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/) authentication, create a copy of the file app/ds_config_sample.py and save the copy as app/ds_config.py.
92-
1. Add your integration key. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **Apps and Integration Keys**, choose the app to use, then select **Actions > Edit**. Under **General Info**, copy the **Integration Key** GUID and save it in ds_config.py as your `ds_client_id`.
93-
1. Generate a secret key, if you don’t already have one. Under **Authentication**, select **+ ADD SECRET KEY**. Copy the secret key and save it in ds_config.py as your `ds_client_secret`.
91+
1. To configure the launcher for [Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/) authentication, create a copy of the file `app/.env.example` and save the copy as `app/.env`.
92+
1. Add your integration key. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **Apps and Integration Keys**, choose the app to use, then select **Actions > Edit**. Under **General Info**, copy the **Integration Key** GUID and save it in .env as your `CLIENT_ID`.
93+
1. Generate a secret key, if you don’t already have one. Under **Authentication**, select **+ ADD SECRET KEY**. Copy the secret key and save it in .env as your `CLIENT_SECRET`.
9494
1. Add the launcher’s redirect URI. Under **Additional settings**, select **+ ADD URI**, and set a redirect URI of http://localhost:3000/ds/callback. Select **SAVE**.
95-
1. Set a name and email address for the signer. In ds_config.py, save an email address as `signer_email` and a name as `signer_name`.
96-
**Note:** Protect your personal information. Please make sure that ds_config.py will not be stored in your source code repository.
95+
1. Set a name and email address for the signer. In .env, save an email address as `SIGNER_EMAIL` and a name as `SIGNER_NAME`.
96+
**Note:** Protect your personal information. Please make sure that .env will not be stored in your source code repository.
9797
1. Run the launcher:`python run.py`
9898
**Note:** You will need to alias the python command to run Python 3 or use `python3 run.py`
9999
1. Open a browser to http://localhost:3000
100100

101101
### Installation steps for JWT Grant authentication
102102

103103
**Note:** If you downloaded this code using [Quickstart](https://developers.docusign.com/docs/esign-rest-api/quickstart/) from the DocuSign Developer Center, skip step 4 as it was automatically performed for you.
104-
Also, in order to select JSON Web Token authentication in the launcher, in app/ds_config.py, change the `quickstart` setting to `"false"`.
104+
Also, in order to select JSON Web Token authentication in the launcher, in app/.env, change the `QUICKSTART_VALUE` setting to `"false"`.
105105

106106
1. Extract the Quickstart ZIP file or download or clone the code-examples-python repository.
107107
1. In your command-line environment, switch to the folder: `cd <Quickstart folder>` or `cd code-examples-python`
108108
1. To install dependencies, run: `pip3 install -r requirements.txt` (or pipenv can be used)
109-
1. To configure the launcher for [JWT Grant](https://developers.docusign.com/platform/auth/jwt/) authentication, create a copy of the file app/ds_config_sample.py and save the copy as app/ds_config.py.
110-
1. Add your User ID. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **My Account Information**, copy the **User ID** GUID and save it in ds_config.py as your `ds_impersonated_user_id`.
111-
1. Add your integration key. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **Apps and Integration Keys**, choose the app to use, then select **Actions > Edit**. Under **General Info**, copy the **Integration Key** GUID and save it in ds_config.py as your `ds_client_id`.
109+
1. To configure the launcher for [JWT Grant](https://developers.docusign.com/platform/auth/jwt/) authentication, create a copy of the file `app/.env.example` and save the copy as `app/.env`.
110+
1. Add your User ID. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **My Account Information**, copy the **User ID** GUID and save it in .env as your `USER_ID`.
111+
1. Add your integration key. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **Apps and Integration Keys**, choose the app to use, then select **Actions > Edit**. Under **General Info**, copy the **Integration Key** GUID and save it in .env as your `CLIENT_ID`.
112112
1. Generate an RSA key pair, if you don’t already have one. Under **Authentication**, select **+ GENERATE RSA**. Copy the private key, and save it in a new file named app/private.key.
113113
1. Add the launcher’s redirect URI. Under **Additional settings**, select **+ ADD URI**, and set a redirect URI of http://localhost:3000/ds/callback. Select **SAVE**.
114-
1. Set a name and email address for the signer. In ds_config.py, save an email address as `signer_email` and a name as `signer_name`.
115-
**Note:** Protect your personal information. Please make sure that your ds_config.py and private.key files will not be stored in your source code repository.
114+
1. Set a name and email address for the signer. In .env, save an email address as `SIGNER_EMAIL` and a name as `SIGNER_NAME`.
115+
**Note:** Protect your personal information. Please make sure that your .env and private.key files will not be stored in your source code repository.
116116
1. Run the launcher:`python run.py`
117117
**Note:** You will need to alias the python command to run Python 3 or use `python3 run.py`
118118
1. Open a browser to http://localhost:3000
@@ -143,7 +143,7 @@ Follow the instructions below if you downloaded the JWT grant remote signing exa
143143

144144
To use the payments code example, create a test payment gateway on the [Payments](https://admindemo.docusign.com/authenticate?goTo=payments) page in your developer account. See [Configure a payment gateway](./PAYMENTS_INSTALLATION.md) for details.
145145

146-
Once you've created a payment gateway, save the **Gateway Account ID** GUID to ds_config.py.
146+
Once you've created a payment gateway, save the **Gateway Account ID** GUID and **Getaway Account Name and Display Name** to .env.
147147

148148

149149
## License and additional information

app/.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CLIENT_ID={CLIENT_ID}
2+
CLIENT_SECRET={CLIENT_SECRET}
3+
USER_ID={USER_ID}
4+
SIGNER_EMAIL={SIGNER_EMAIL}
5+
SIGNER_NAME={SIGNER_NAME}
6+
DS_PAYMENT_GATEWAY_ID={DS_PAYMENT_GATEWAY_ID}
7+
DS_PAYMENT_GATEWAY_NAME={DS_PAYMENT_GATEWAY_NAME}
8+
DS_PAYMENT_GATEWAY_DISPLAY_NAME={DS_PAYMENT_GATEWAY_DISPLAY_NAME}
9+
QUICKSTART_VALUE={QUICKSTART_VALUE}

app/click/examples/eg006_embed_clickwrap.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ def worker(args):
5656
user_agreement_request = UserAgreementRequest(
5757
client_user_id=args["email"],
5858
document_data={
59-
"fullName": args["fullName"],
60-
"email": args["email"],
61-
"company": args["company"],
62-
"title": args["title"],
59+
"fullName": args["fullName"],
60+
"email": args["email"],
61+
"company": args["company"],
62+
"title": args["title"],
6363
"date": args["date"]
64-
},
64+
},
6565
)
6666

6767
# Retrieve Agreement Url using SDK

app/docusign/views.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def ds_login():
2020
if not session.get("auth_type"):
2121
session["auth_type"] = request.form.get("auth_type")
2222

23+
session["manifest"] = get_manifest(manifest_url)
24+
2325
app.config["isLoggedIn"] = True
2426
app.config["quickstart"] = DS_CONFIG["quickstart"]
2527
return DSClient.login(session["auth_type"], session.get("api"))
Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
#
33
# DocuSign configuration settings
44

5+
import os
6+
from dotenv import load_dotenv
7+
8+
9+
load_dotenv()
10+
511
DS_CONFIG = {
6-
"ds_client_id": "{INTEGRATION_KEY_AUTH_CODE}", # The app's DocuSign integration key
7-
"ds_client_secret": "{SECRET_KEY}", # The app's DocuSign integration key's secret
8-
"organization_id": "{ORGANIZATION_ID}", # A GUID value that identifies the organization
9-
"signer_email": "{SIGNER_EMAIL}",
10-
"signer_name": "{SIGNER_NAME}",
11-
"app_url": "http://localhost:3000", # The URL of the application. Eg http://localhost:5000
12+
"ds_client_id": os.environ.get("CLIENT_ID"), # The app's DocuSign integration key
13+
"ds_client_secret": os.environ.get("CLIENT_SECRET"), # The app's DocuSign integration key's secret
14+
"signer_email": os.environ.get("SIGNER_EMAIL"),
15+
"signer_name": os.environ.get("SIGNER_NAME"),
16+
"app_url": "http://localhost:5000", # The URL of the application. Eg http://localhost:5000
1217
# NOTE: You must add a Redirect URI of appUrl/ds/callback to your Integration Key.
1318
# Example: http://localhost:5000/ds/callback
1419
"authorization_server": "https://account-d.docusign.com",
@@ -27,21 +32,22 @@
2732
"doc_terms_pdf": "Term_Of_Service.pdf",
2833
"doc_txt": "Welcome.txt",
2934
# Payment gateway information is optional
30-
"gateway_account_id": "{DS_PAYMENT_GATEWAY_ID}",
31-
"gateway_name": "stripe",
32-
"gateway_display_name": "Stripe",
35+
"gateway_account_id": os.environ.get("DS_PAYMENT_GATEWAY_ID"),
36+
"gateway_name": os.environ.get("DS_PAYMENT_GATEWAY_NAME"),
37+
"gateway_display_name": os.environ.get("DS_PAYMENT_GATEWAY_DISPLAY_NAME"),
3338
"github_example_url": "https://github.com/docusign/code-examples-python/tree/master/app/eSignature/examples/",
3439
"monitor_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/monitor/examples/",
3540
"admin_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/admin/examples/",
3641
"click_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/click/examples/",
37-
"example_manifest_url": "https://raw.githubusercontent.com/docusign/code-examples-csharp/master/manifest/CodeExamplesManifest.json",
42+
"example_manifest_url": "https://raw.githubusercontent.com/annahileta/ManifestsForCodeExamples/main/CodeExamplesManifest.json",
3843
"documentation": "", # Use an empty string to indicate no documentation path.
39-
"quickstart": "{QUICKSTART_VALUE}"
44+
"quickstart": os.environ.get("QUICKSTART_VALUE"),
45+
"quick_acg": False
4046
}
4147

4248
DS_JWT = {
43-
"ds_client_id": "{INTEGRATION_KEY_JWT}",
44-
"ds_impersonated_user_id": "{IMPERSONATED_USER_ID}", # The id of the user.
49+
"ds_client_id": os.environ.get("CLIENT_ID"),
50+
"ds_impersonated_user_id": os.environ.get("USER_ID"), # The id of the user.
4551
"private_key_file": "./app/private.key", # Create a new file in your repo source folder named private.key then copy and paste your RSA private key there and save it.
4652
"authorization_server": "account-d.docusign.com"
4753
}

app/tests/test_helper.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,19 @@
55

66
from ..ds_config import DS_CONFIG, DS_JWT
77

8+
9+
CONFIG = {
10+
"ds_client_id": DS_JWT["ds_client_id"],
11+
"ds_impersonated_user_id": DS_JWT["ds_impersonated_user_id"],
12+
"signer_email": DS_CONFIG["signer_email"],
13+
"signer_name": DS_CONFIG["signer_name"],
14+
"private_key_file": DS_JWT["private_key_file"]
15+
}
16+
817
DATA = {
918
"signer_client_id": '1000',
10-
"return_url": DS_CONFIG["app_url"] + "/ds-return",
11-
"ping_url": DS_CONFIG["app_url"] + "/",
19+
"return_url": "http://localhost:5000/ds-return",
20+
"ping_url": "http://localhost:5000/",
1221
"private_key_filename": "../config/private.key",
1322
"base_path": 'https://demo.docusign.net/restapi',
1423
"oauth_base_path": 'account-d.docusign.com',
@@ -31,7 +40,7 @@ class TestHelper:
3140
@staticmethod
3241
def authenticate():
3342
try:
34-
private_key_file = open(os.path.abspath(os.path.join(DS_JWT["private_key_file"])), "r")
43+
private_key_file = open(os.path.abspath(os.path.join(CONFIG["private_key_file"])), "r")
3544
private_key = private_key_file.read()
3645

3746
api_client = ApiClient()
@@ -41,11 +50,11 @@ def authenticate():
4150
api_client.set_base_path(DATA["base_path"])
4251
api_client.set_oauth_host_name(DATA["oauth_base_path"])
4352
token_response = api_client.request_jwt_user_token(
44-
client_id=DS_JWT["ds_client_id"],
45-
user_id=DS_JWT["ds_impersonated_user_id"],
53+
client_id=CONFIG["ds_client_id"],
54+
user_id=CONFIG["ds_impersonated_user_id"],
4655
oauth_host_name=DATA["oauth_base_path"],
4756
private_key_bytes=private_key,
48-
expires_in=4000,
57+
expires_in=DATA["expires_in"],
4958
scopes=DATA["scopes"]
5059
)
5160

@@ -63,8 +72,8 @@ def authenticate():
6372

6473
if "consent_required" in body:
6574
url_scopes = "+".join(DATA["scopes"])
66-
url = f"https://{DS_JWT['authorization_server']}/oauth/auth?response_type=code&" \
67-
f"scope={url_scopes}&client_id={DS_JWT['ds_client_id']}&redirect_uri={DATA['redirect_uri']}"
75+
url = f"https://{DATA['oauth_base_path']}/oauth/auth?response_type=code&" \
76+
f"scope={url_scopes}&client_id={CONFIG['ds_client_id']}&redirect_uri={DATA['redirect_uri']}"
6877

6978
consent_message = f"You should grant access by making the following call: {url}"
7079
print(consent_message)
@@ -77,4 +86,3 @@ def read_as_base64(path):
7786
base64_file_content = base64.b64encode(content_bytes).decode("ascii")
7887

7988
return base64_file_content
80-

0 commit comments

Comments
 (0)