diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 3ce85827..9b0931db 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -19,4 +19,7 @@ jobs: - name: Validate Files run: python ci/validate.py + + - name: Generate Code Blocks + run: python ci/copy_code_blocks.py \ No newline at end of file diff --git a/authentication-guides/asana/.codeblocks/block_0.sh b/authentication-guides/asana/.codeblocks/block_0.sh new file mode 100644 index 00000000..9307ad62 --- /dev/null +++ b/authentication-guides/asana/.codeblocks/block_0.sh @@ -0,0 +1,2 @@ +curl https://app.asana.com/api/1.0/users/me \ + -H "Authorization: Bearer {{YOUR_PERSONAL_ACCESS_TOKEN}}" diff --git a/authentication-guides/asana/.codeblocks/block_1.sh b/authentication-guides/asana/.codeblocks/block_1.sh new file mode 100644 index 00000000..9307ad62 --- /dev/null +++ b/authentication-guides/asana/.codeblocks/block_1.sh @@ -0,0 +1,2 @@ +curl https://app.asana.com/api/1.0/users/me \ + -H "Authorization: Bearer {{YOUR_PERSONAL_ACCESS_TOKEN}}" diff --git a/authentication-guides/asana/.codeblocks/block_2.json b/authentication-guides/asana/.codeblocks/block_2.json new file mode 100644 index 00000000..0e0a52d0 --- /dev/null +++ b/authentication-guides/asana/.codeblocks/block_2.json @@ -0,0 +1,9 @@ + +{ + "data": { + "email": "************", + "gid": "1200311869439617", + "name": "Ajay Merchia", + ... + } +} diff --git a/authentication-guides/asana/README.md b/authentication-guides/asana/README.md index 523e15e6..ed0b8a72 100644 --- a/authentication-guides/asana/README.md +++ b/authentication-guides/asana/README.md @@ -57,7 +57,7 @@ Asana's API provides a robust platform to integrate and streamline tasks in your - Api Key: `{{your_personal_access_token}}` 2. Define your API action for channel creation. - ```python + ```bash curl https://app.asana.com/api/1.0/users/me \ -H "Authorization: Bearer {{YOUR_PERSONAL_ACCESS_TOKEN}}" ``` @@ -66,7 +66,7 @@ Asana's API provides a robust platform to integrate and streamline tasks in your - Method: `GET` 3. Test your setup in Creator Studio and look for a successful execution. - ```bash + ```json { "data": { diff --git a/authentication-guides/slack/.codeblocks/block_0.sh b/authentication-guides/slack/.codeblocks/block_0.sh new file mode 100644 index 00000000..e080bdc5 --- /dev/null +++ b/authentication-guides/slack/.codeblocks/block_0.sh @@ -0,0 +1,3 @@ +curl -X POST 'https://slack.com/api/conversations.create' \ +--header 'Authorization: Bearer {{xoxb_your_bot_access_token}}' \ +--data-urlencode 'name=test-channel' diff --git a/authentication-guides/slack/.codeblocks/block_1.sh b/authentication-guides/slack/.codeblocks/block_1.sh new file mode 100644 index 00000000..98ff5df8 --- /dev/null +++ b/authentication-guides/slack/.codeblocks/block_1.sh @@ -0,0 +1,3 @@ +curl -X POST '{{base_url}}/conversations.create' \ +--header 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'name={{channel-name}}' diff --git a/authentication-guides/slack/.codeblocks/block_2.txt b/authentication-guides/slack/.codeblocks/block_2.txt new file mode 100644 index 00000000..ca09dbab --- /dev/null +++ b/authentication-guides/slack/.codeblocks/block_2.txt @@ -0,0 +1 @@ +name=channel-name diff --git a/authentication-guides/slack/.codeblocks/block_3.json b/authentication-guides/slack/.codeblocks/block_3.json new file mode 100644 index 00000000..1dab27d6 --- /dev/null +++ b/authentication-guides/slack/.codeblocks/block_3.json @@ -0,0 +1,10 @@ + +{ + "ok": true, + "channel": { + "id": "C1234567890", + "name": "channel-name", + "is_channel": true, + ... + } +} diff --git a/authentication-guides/slack/README.md b/authentication-guides/slack/README.md index 20e3c598..382ff78c 100644 --- a/authentication-guides/slack/README.md +++ b/authentication-guides/slack/README.md @@ -75,7 +75,7 @@ Slack's API provides a powerful way to automate tasks in your Slack workspace. T - Api Key: `{{xoxb_your_bot_access_token}}` 2. Define your API action for channel creation. - ```python + ```bash curl -X POST '{{base_url}}/conversations.create' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'name={{channel-name}}' @@ -91,14 +91,14 @@ Slack's API provides a powerful way to automate tasks in your Slack workspace. T | Content-Type | application/x-www-form-urlencoded | - Body: - ``` + ```text name=channel-name ``` 3. Test your setup in Creator Studio and look for a successful execution. - ```bash + ```json { "ok": true, diff --git a/authentication-guides/workato/.codeblocks/block_0.json b/authentication-guides/workato/.codeblocks/block_0.json new file mode 100644 index 00000000..e82c1178 --- /dev/null +++ b/authentication-guides/workato/.codeblocks/block_0.json @@ -0,0 +1,3 @@ +{ + "name": "Luke" +} diff --git a/authentication-guides/workato/.codeblocks/block_1.sh b/authentication-guides/workato/.codeblocks/block_1.sh new file mode 100644 index 00000000..d4696752 --- /dev/null +++ b/authentication-guides/workato/.codeblocks/block_1.sh @@ -0,0 +1,6 @@ +curl --location '{{recipe_url}}' \ +--header 'Content-Type: application/json' \ +--header 'api-token: {{access_token}}' \ +--data '{ + "name": "Luke" +}' diff --git a/authentication-guides/workato/.codeblocks/block_2.sh b/authentication-guides/workato/.codeblocks/block_2.sh new file mode 100644 index 00000000..3b6bb233 --- /dev/null +++ b/authentication-guides/workato/.codeblocks/block_2.sh @@ -0,0 +1,2 @@ +curl --location '{{base_url}}/mw/ajay-merchia-vv1/reverse-echo' \ +--data '' diff --git a/authentication-guides/workato/.codeblocks/block_3.json b/authentication-guides/workato/.codeblocks/block_3.json new file mode 100644 index 00000000..0f16faec --- /dev/null +++ b/authentication-guides/workato/.codeblocks/block_3.json @@ -0,0 +1,3 @@ +{ + "name": "{{query}}" +} diff --git a/authentication-guides/workato/.codeblocks/block_4.json b/authentication-guides/workato/.codeblocks/block_4.json new file mode 100644 index 00000000..2e278f43 --- /dev/null +++ b/authentication-guides/workato/.codeblocks/block_4.json @@ -0,0 +1,3 @@ +{ + "reversed_name": "ekuL" +} diff --git a/authentication-guides/workato/README.md b/authentication-guides/workato/README.md index df51e98d..5e01d347 100644 --- a/authentication-guides/workato/README.md +++ b/authentication-guides/workato/README.md @@ -33,7 +33,7 @@ We are going to build a simple “Reverse Echo” API that returns the value sen 3. Provide the sample payload, then click `Generate Schema` - ```bash + ```json { "name": "Luke" } @@ -141,7 +141,7 @@ We are going to build a simple “Reverse Echo” API that returns the value sen - API Key: `{{access_key}}` 2. Add your API details. You can read more about setting up API actions from our [API configuration reference](https://developer.moveworks.com/creator-studio/api-configuration/). - ```python + ```bash curl --location '{{base_url}}/mw/ajay-merchia-vv1/reverse-echo' \ --data '' ``` @@ -150,7 +150,7 @@ We are going to build a simple “Reverse Echo” API that returns the value sen - Method: `POST` - Body: - ```bash + ```json { "name": "{{query}}" } @@ -159,7 +159,7 @@ We are going to build a simple “Reverse Echo” API that returns the value sen - Example Value: `Luke` 3. Hit test & celebrate! - ```bash + ```json { "reversed_name": "ekuL" } diff --git a/ci/copy_code_blocks.py b/ci/copy_code_blocks.py new file mode 100644 index 00000000..4eb66517 --- /dev/null +++ b/ci/copy_code_blocks.py @@ -0,0 +1,136 @@ +import os +import sys +from markdown_it import MarkdownIt +from markdown_it.rules_block import StateBlock +from pygments.lexers import get_lexer_by_name, guess_lexer +from typing import List + + +def find_markdown_files(directory_path): + markdown_files = [] + for dirpath, _, files in os.walk(directory_path): + for file_name in files: + if file_name.endswith(".md"): + markdown_files.append(os.path.join(dirpath, file_name)) + return markdown_files + + +def detect_language(code): + language_keywords = [ # Extends the Lexer if it fails + # ("*.py", ["def", "import", "print"]), # Example line -- to be updated as needed + ] + for ext, keywords in language_keywords: + if any(keyword in code for keyword in keywords): + return ext + try: + guessed_lexer = guess_lexer(code) + return guessed_lexer.aliases[0] + except ValueError: + return None + + +def extract_code_blocks_from_file(file_path: str): + mdit = MarkdownIt("commonmark") + code_blocks = [] + + with open(file_path, "r") as f: + md_content = f.read() + tokens = mdit.parse(md_content) + + for token in tokens: + if token.type == "fence" and token.content: + language_extension = detect_language(token.content) + try: + lexer = get_lexer_by_name(token.info.strip()) + language_extension = lexer.filenames[0] + + + except ValueError: + print(f"Warning: No explicit language defined for code block in {file_path}:\n{token.content}") + + if language_extension == "text": + language_extension = "*.txt" + + code_blocks.append( + { + "index": len(code_blocks), + "file_extension": language_extension, + "contents": token.content, + } + ) + return code_blocks + + +def create_code_files_from_blocks(file_path: str, code_blocks: List[dict]): + directory = os.path.join(os.path.dirname(file_path), ".codeblocks") + os.makedirs(directory, exist_ok=True) + + # if we have no code blocks, delete the dir if exists and exit early + if not code_blocks: + if os.path.exists(directory) and os.path.isdir(directory): + os.rmdir(directory) + return False, [] + + original_files = set(os.listdir(directory)) # get all files currently in directory + newly_created_files = set() # store the names of created/modified files + changes_made = False + + for block in code_blocks: + file_extension = block["file_extension"].lstrip("*") + filename = f"block_{block['index']}{file_extension}" + blob_file_path = os.path.join(directory, filename) + + # check if file already exists + if os.path.exists(blob_file_path): + with open(blob_file_path, "r") as blob_file: + existing_data = blob_file.read() + # check if contents are the same, if not update it + if existing_data != block["contents"]: + changes_made = True + else: + changes_made = True + + # Write file + with open(blob_file_path, "w") as blob_file: + blob_file.write(block["contents"]) + newly_created_files.add(filename) + + # delete all untouched files + for old_file in original_files.difference(newly_created_files): + os.remove(os.path.join(directory, old_file)) + + return changes_made, list(newly_created_files) + + +def main(): + guide_files = find_markdown_files("./authentication-guides") + guide_files += find_markdown_files("./use-case-guides") + guide_files += find_markdown_files("./design-patterns") + + changes_made_anywhere = False + + summary = {} + + for f in guide_files: + code_blocks = extract_code_blocks_from_file(f) + change_detected, created_files = create_code_files_from_blocks(f, code_blocks) + summary[f] = len(code_blocks) + + if change_detected: + print( + f"Change detected in file '{f}'. Created/modified the following files:" + ) + print("\n".join(created_files)) + changes_made_anywhere = True + print("----------------------------") + + if changes_made_anywhere: + sys.exit(1) + else: + print("All code blocks are up to date.") + for fn, num_blocks in summary.items(): + print(fn, num_blocks) + + +if __name__ == "__main__": + main() diff --git a/ci/requirements.txt b/ci/requirements.txt index 5500f007..056d8b49 100644 --- a/ci/requirements.txt +++ b/ci/requirements.txt @@ -1 +1,3 @@ PyYAML +markdown-it-py==2.0.1 +Pygments==2.8.1 \ No newline at end of file diff --git a/use-case-guides/rename-slack-channel/.codeblocks/block_0.py b/use-case-guides/rename-slack-channel/.codeblocks/block_0.py new file mode 100644 index 00000000..61836509 --- /dev/null +++ b/use-case-guides/rename-slack-channel/.codeblocks/block_0.py @@ -0,0 +1,4 @@ +{ + "old_name": "{{previous channel name}}", + "new_name": "{{name of new channel}}" +}