Skip to content
Open
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,7 @@
# TYPEFORM_TEST_FORM_ID=
# Optional: existing workspace ID for get_workspace (falls back to list_workspaces if unset).
# TYPEFORM_TEST_WORKSPACE_ID=

# -- Netlify --
# Personal access token for the Netlify API.
# NETLIFY_ACCESS_TOKEN=
34 changes: 3 additions & 31 deletions netlify/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Netlify",
"display_name": "Netlify",
"version": "1.0.0",
"version": "2.0.0",
"description": "Integration with Netlify for managing sites, deployments, and hosting",
"entry_point": "netlify.py",
"auth": {
Expand All @@ -24,10 +24,6 @@
"sites": {
"type": "array",
"description": "List of sites"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand Down Expand Up @@ -55,10 +51,6 @@
"site": {
"type": "object",
"description": "Created site details"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand All @@ -82,10 +74,6 @@
"site": {
"type": "object",
"description": "Site details"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand All @@ -106,9 +94,9 @@
"output_schema": {
"type": "object",
"properties": {
"result": {
"deleted": {
"type": "boolean",
"description": "Operation success status"
"description": "Whether the site was successfully deleted"
}
}
}
Expand All @@ -132,10 +120,6 @@
"deploys": {
"type": "array",
"description": "List of deploys"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand Down Expand Up @@ -167,10 +151,6 @@
"deploy_url": {
"type": "string",
"description": "URL of the deployed site"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand All @@ -194,10 +174,6 @@
"deploy": {
"type": "object",
"description": "Deploy details"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand Down Expand Up @@ -229,10 +205,6 @@
"site": {
"type": "object",
"description": "Updated site details"
},
"result": {
"type": "boolean",
"description": "Operation success status"
}
}
}
Expand Down
54 changes: 31 additions & 23 deletions netlify/netlify.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from autohive_integrations_sdk import Integration, ExecutionContext, ActionHandler, ActionResult
from autohive_integrations_sdk import Integration, ExecutionContext, ActionHandler, ActionResult, ActionError
from typing import Dict, Any
import hashlib

Expand All @@ -23,12 +23,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
try:
response = await context.fetch(f"{NETLIFY_API_BASE_URL}/sites", method="GET")

sites = response if isinstance(response, list) else []
sites = response.data if isinstance(response.data, list) else []

return ActionResult(data={"sites": sites, "result": True}, cost_usd=0.0)
return ActionResult(data={"sites": sites}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"sites": [], "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


@netlify.action("create_site")
Expand All @@ -46,10 +46,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):

response = await context.fetch(f"{NETLIFY_API_BASE_URL}/sites", method="POST", json=payload)

return ActionResult(data={"site": response, "result": True}, cost_usd=0.0)
return ActionResult(data={"site": response.data}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"site": {}, "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


@netlify.action("get_site")
Expand All @@ -62,10 +62,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):

response = await context.fetch(f"{NETLIFY_API_BASE_URL}/sites/{site_id}", method="GET")

return ActionResult(data={"site": response, "result": True}, cost_usd=0.0)
return ActionResult(data={"site": response.data}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"site": {}, "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


@netlify.action("update_site")
Expand All @@ -84,10 +84,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):

response = await context.fetch(f"{NETLIFY_API_BASE_URL}/sites/{site_id}", method="PATCH", json=payload)

return ActionResult(data={"site": response, "result": True}, cost_usd=0.0)
return ActionResult(data={"site": response.data}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"site": {}, "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


@netlify.action("delete_site")
Expand All @@ -100,10 +100,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):

await context.fetch(f"{NETLIFY_API_BASE_URL}/sites/{site_id}", method="DELETE")

return ActionResult(data={"deleted": True, "result": True}, cost_usd=0.0)
return ActionResult(data={"deleted": True}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"deleted": False, "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


# ---- Deploy Handlers ----
Expand All @@ -119,12 +119,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):

response = await context.fetch(f"{NETLIFY_API_BASE_URL}/sites/{site_id}/deploys", method="GET")

deploys = response if isinstance(response, list) else []
deploys = response.data if isinstance(response.data, list) else []

return ActionResult(data={"deploys": deploys, "result": True}, cost_usd=0.0)
return ActionResult(data={"deploys": deploys}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"deploys": [], "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


@netlify.action("create_deploy")
Expand All @@ -139,43 +139,51 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
# Prepare files dictionary with SHA1 hashes
files_dict = {}
hash_to_content = {}
hash_to_path = {}

for path, content in files.items():
sha1 = hashlib.sha1(content.encode(), usedforsecurity=False).hexdigest() # nosec B324
files_dict[path] = sha1
hash_to_content[sha1] = content
if sha1 not in hash_to_content:
hash_to_content[sha1] = content
hash_to_path[sha1] = path

# Create deploy with file digests
deploy = await context.fetch(
deploy_response = await context.fetch(
f"{NETLIFY_API_BASE_URL}/sites/{site_id}/deploys", method="POST", json={"files": files_dict}
)
deploy = deploy_response.data

# Upload required files
required_hashes = deploy.get("required", [])
deploy_id = deploy.get("id")
if not deploy_id:
raise ValueError("Netlify did not return a deploy ID — cannot upload files or retrieve deploy status")

for sha1_hash in required_hashes:
if sha1_hash in hash_to_content:
file_content = hash_to_content[sha1_hash]
file_path = hash_to_path[sha1_hash]

await context.fetch(
f"{NETLIFY_API_BASE_URL}/deploys/{deploy_id}/files/{sha1_hash}",
f"{NETLIFY_API_BASE_URL}/deploys/{deploy_id}/files{file_path}",
method="PUT",
headers={"Content-Type": "application/octet-stream"},
data=file_content.encode(),
)

# Get final deploy info
final_deploy = await context.fetch(f"{NETLIFY_API_BASE_URL}/deploys/{deploy_id}", method="GET")
final_response = await context.fetch(f"{NETLIFY_API_BASE_URL}/deploys/{deploy_id}", method="GET")
final_deploy = final_response.data

deploy_url = (
final_deploy.get("deploy_ssl_url") or final_deploy.get("ssl_url") or final_deploy.get("url", "")
)

return ActionResult(data={"deploy": final_deploy, "deploy_url": deploy_url, "result": True}, cost_usd=0.0)
return ActionResult(data={"deploy": final_deploy, "deploy_url": deploy_url}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"deploy": {}, "deploy_url": "", "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))


@netlify.action("get_deploy")
Expand All @@ -188,7 +196,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):

response = await context.fetch(f"{NETLIFY_API_BASE_URL}/deploys/{deploy_id}", method="GET")

return ActionResult(data={"deploy": response, "result": True}, cost_usd=0.0)
return ActionResult(data={"deploy": response.data}, cost_usd=0.0)

except Exception as e:
return ActionResult(data={"deploy": {}, "result": False, "error": str(e)}, cost_usd=0.0)
return ActionError(message=str(e))
2 changes: 1 addition & 1 deletion netlify/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
autohive-integrations-sdk~=1.0.2
autohive-integrations-sdk~=2.0.0
1 change: 0 additions & 1 deletion netlify/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
# Netlify Integration Tests
2 changes: 0 additions & 2 deletions netlify/tests/context.py → netlify/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@
import sys

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from netlify import netlify
Loading
Loading