Skip to content

Commit

Permalink
Merge pull request #683 from linode/dev
Browse files Browse the repository at this point in the history
Release v5.55.0
  • Loading branch information
yec-akamai authored Nov 21, 2024
2 parents 8bc7bbe + 5bab33a commit 62bdfa7
Show file tree
Hide file tree
Showing 48 changed files with 1,905 additions and 401 deletions.
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ updates:
directory: "/" # Location of package manifests
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
21 changes: 11 additions & 10 deletions .github/workflows/e2e-suite-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ on:
pull_request:
workflow_dispatch:
inputs:
test_path:
description: "The path from 'test/integration' to the target to be tested, e.g. 'cli'"
module:
description: "The module from 'test/integration' to the target to be tested, e.g. 'cli, domains, events, etc'"
required: false
run_long_tests:
description: "Select True to run long tests, e.g. database, rebuild, etc"
required: false
type: choice
options:
- "True"
- "False"
default: "False"
sha:
description: 'The hash value of the commit.'
required: true
Expand All @@ -21,13 +29,6 @@ jobs:
github.event_name == 'workflow_dispatch' && inputs.sha != ''

steps:
- uses: actions-ecosystem/action-regex-match@v2
id: validate-tests
with:
text: ${{ inputs.test_path }}
regex: '[^a-z0-9-:.\/_]' # Tests validation
flags: gi

# Check out merge commit
- name: Checkout PR
uses: actions/checkout@v4
Expand Down Expand Up @@ -72,7 +73,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- run: make INTEGRATION_TEST_PATH="${{ inputs.test_path }}" testint
- run: make MODULE="${{ inputs.module }}" RUN_LONG_TESTS="${{ inputs.run_long_tests }}" testint
env:
LINODE_CLI_TOKEN: ${{ secrets.LINODE_TOKEN_2 }}

Expand Down
37 changes: 33 additions & 4 deletions .github/workflows/e2e-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,47 @@ on:
module:
description: "The module from 'test/integration' to the target to be tested, e.g. 'cli, domains, events, etc'"
required: false
run_long_tests:
description: "Select True to run long tests, e.g. database, rebuild, etc"
required: false
type: choice
options:
- "True"
- "False"
default: "False"
sha:
description: 'The hash value of the commit.'
required: true
default: ''
pull_request_number:
description: 'The number of the PR. Ensure sha value is provided'
required: false
openapi_spec_url:
description: 'URL of the OpenAPI spec to use for the tests'
required: false
default: ''
python-version:
description: 'Specify Python version to use'
required: false
run-eol-python-version:
description: 'Run EOL python version?'
required: false
default: 'false'
type: choice
options:
- 'true'
- 'false'

push:
branches:
- main
- dev

env:
DEFAULT_PYTHON_VERSION: "3.10"
EOL_PYTHON_VERSION: "3.8"
EXIT_STATUS: 0

jobs:
integration_tests:
name: Run integration tests on Ubuntu
Expand Down Expand Up @@ -74,7 +103,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
python-version: ${{ inputs.run-eol-python-version == 'true' && env.EOL_PYTHON_VERSION || inputs.python-version || env.DEFAULT_PYTHON_VERSION }}

- name: Install Python dependencies and update cert
run: |
Expand All @@ -83,7 +112,7 @@ jobs:
pip install .[obj,dev]
- name: Install Package
run: make install
run: make install SPEC="${{ inputs.OPENAPI_SPEC_URL }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand All @@ -95,7 +124,7 @@ jobs:
run: |
timestamp=$(date +'%Y%m%d%H%M')
report_filename="${timestamp}_cli_test_report.xml"
make testint TEST_ARGS="--junitxml=${report_filename}" MODULE="${{ inputs.module }}"
make testint TEST_ARGS="--junitxml=${report_filename}" MODULE="${{ inputs.module }}" RUN_LONG_TESTS="${{ inputs.run_long_tests }}"
env:
LINODE_CLI_TOKEN: ${{ env.LINODE_CLI_TOKEN }}

Expand Down Expand Up @@ -272,4 +301,4 @@ jobs:
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4
-
name: Run Labeler
uses: crazy-max/ghaction-github-labeler@de749cf181958193cb7debf1a9c5bb28922f3e1b
uses: crazy-max/ghaction-github-labeler@b54af0c25861143e7c8813d7cbbf46d2c341680c
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
yaml-file: .github/labels.yml
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-oci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ jobs:
run: make requirements

- name: Set up QEMU
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # pin@v2.2.0
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3.2.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@ecf95283f03858871ff00b787d79c419715afc34 # [email protected]

- name: Login to Docker Hub
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # pin@v2.2.0
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/remote-release-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
steps:
- name: Generate App Installation Token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 # pin@v1
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # pin@v1
with:
app_id: ${{ secrets.CLI_RELEASE_APP_ID }}
private_key: ${{ secrets.CLI_RELEASE_PRIVATE_KEY }}
Expand All @@ -23,7 +23,7 @@ jobs:

- name: Get previous tag
id: previoustag
uses: WyriHaximus/github-action-get-previous-tag@385a2a0b6abf6c2efeb95adfac83d96d6f968e0c # pin@v1
uses: WyriHaximus/github-action-get-previous-tag@04e8485ecb6487243907e330d522ff60f02283ce # pin@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
jobs:
unit-tests-on-ubuntu:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.9','3.10','3.11', '3.12' ]
steps:
- name: Clone Repository
uses: actions/checkout@v3
Expand All @@ -14,9 +17,9 @@ jobs:
run: sudo apt-get update -y

- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.x'
python-version: ${{ matrix.python-version }}

- name: Install Python wheel
run: pip install wheel boto3
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ testunit:
@orig_xdg_config_home=$${XDG_CONFIG_HOME:-}; \
export LINODE_CLI_TEST_MODE=1 XDG_CONFIG_HOME=/tmp/linode/.config; \
pytest -v tests/unit; \
export XDG_CONFIG_HOME=$$orig_xdg_config_home
exit_code=$$?; \
export XDG_CONFIG_HOME=$$orig_xdg_config_home; \
exit $$exit_code

.PHONY: testint
testint:
Expand Down
1 change: 1 addition & 0 deletions linodecli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,5 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
if parsed.help:
print_help_action(cli, parsed.command, parsed.action)
sys.exit(ExitCodes.SUCCESS)

cli.handle_command(parsed.command, parsed.action, args)
4 changes: 3 additions & 1 deletion linodecli/api_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,13 @@ def _build_request_body(ctx, operation, parsed_args) -> Optional[str]:
if ctx.defaults:
parsed_args = ctx.config.update(parsed_args, operation.allowed_defaults)

param_names = {param.name for param in operation.params}

expanded_json = {}

# expand paths
for k, v in vars(parsed_args).items():
if v is None:
if v is None or k in param_names:
continue

cur = expanded_json
Expand Down
31 changes: 28 additions & 3 deletions linodecli/baked/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import openapi3.paths
from openapi3.paths import Operation, Parameter

from linodecli.baked.parsing import simplify_description
from linodecli.baked.request import OpenAPIFilteringRequest, OpenAPIRequest
from linodecli.baked.response import OpenAPIResponse
from linodecli.exit_codes import ExitCodes
Expand Down Expand Up @@ -356,8 +357,12 @@ def __init__(
self.action_aliases = {}
self.action = action

self.summary = operation.summary
self.description = operation.description.split(".")[0]
# Ensure the summary has punctuation
self.summary = operation.summary.rstrip(".") + "."

self.description_rich, self.description = simplify_description(
operation.description or ""
)

# The apiVersion attribute should not be specified as a positional argument
self.params = [
Expand All @@ -366,6 +371,20 @@ def __init__(
if param.name not in {"apiVersion"}
]

# Validation to ensure no conflicting arguments & param names are found.
# This is necessary because arguments and parameters are both parsed into the
# same result namespace by argparse.
if self.request is not None and hasattr(self.request, "attrs"):
param_names = {param.name for param in self.params}

for attr in self.request.attrs:
if attr not in param_names:
continue

raise ValueError(
f"Attribute {attr.name} conflicts with parameter of the same name"
)

(
self.url_base,
self.url_path,
Expand Down Expand Up @@ -447,7 +466,13 @@ def _resolve_api_version(
None,
)
if version_param is not None:
return version_param.schema.default
schema = version_param.schema

if schema.default:
return schema.default

if schema.enum and len(schema.enum) > 0:
return schema.enum[0]

return None

Expand Down
54 changes: 31 additions & 23 deletions linodecli/baked/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
import functools
import re
from html import unescape
from typing import List, Tuple
from typing import List, Optional, Tuple

# Sentence delimiter, split on a period followed by any type of
# whitespace (space, new line, tab, etc.)
REGEX_SENTENCE_DELIMITER = re.compile(r"\W(?:\s|$)")
REGEX_SENTENCE_DELIMITER = re.compile(r"\.(?:\s|$)", flags=re.M)

# Matches on pattern __prefix__ at the beginning of a description
# or after a comma
REGEX_TECHDOCS_PREFIX = re.compile(r"(?:, |\A)__([\w-]+)__")
REGEX_TECHDOCS_PREFIX = re.compile(r"(?:, |\A)__([^_]+)__")

# Matches on pattern [link title](https://.../)
REGEX_MARKDOWN_LINK = re.compile(r"\[(?P<text>.*?)]\((?P<link>.*?)\)")
Expand Down Expand Up @@ -121,23 +121,35 @@ def get_short_description(description: str) -> str:
:rtype: set
"""

target_lines = description.splitlines()
relevant_lines = None

for i, line in enumerate(target_lines):
def __simplify(sentence: str) -> Optional[str]:
# Edge case for descriptions starting with a note
if line.lower().startswith("__note__"):
continue
if sentence.lower().startswith("__note__"):
return None

sentence = strip_techdocs_prefixes(sentence)

relevant_lines = target_lines[i:]
break
# Check that the sentence still has content after stripping prefixes
if len(sentence) < 2:
return None

if relevant_lines is None:
return sentence + "."

# Find the first relevant sentence
result = next(
simplified
for simplified in iter(
__simplify(sentence)
for sentence in REGEX_SENTENCE_DELIMITER.split(description)
)
if simplified is not None
)

if result is None:
raise ValueError(
f"description does not contain any relevant lines: {description}",
)

return REGEX_SENTENCE_DELIMITER.split("\n".join(relevant_lines), 1)[0] + "."
return result


def strip_techdocs_prefixes(description: str) -> str:
Expand All @@ -150,14 +162,10 @@ def strip_techdocs_prefixes(description: str) -> str:
:returns: The stripped description
:rtype: str
"""
result_description = REGEX_TECHDOCS_PREFIX.sub(
"", description.lstrip()
).lstrip()

return result_description
return REGEX_TECHDOCS_PREFIX.sub("", description.lstrip()).lstrip()


def process_arg_description(description: str) -> Tuple[str, str]:
def simplify_description(description: str) -> Tuple[str, str]:
"""
Processes the given raw request argument description into one suitable
for help pages, etc.
Expand All @@ -173,12 +181,12 @@ def process_arg_description(description: str) -> Tuple[str, str]:
return "", ""

result = get_short_description(description)
result = strip_techdocs_prefixes(result)
result = result.replace("\n", " ").replace("\r", " ")

description, links = extract_markdown_links(result)
# NOTE: Links should only be separated from Rich Markdown links
result_no_links, links = extract_markdown_links(result)

if len(links) > 0:
description += f" See: {'; '.join(links)}"
result_no_links += f" See: {'; '.join(links)}"

return unescape(markdown_to_rich_markup(description)), unescape(description)
return unescape(markdown_to_rich_markup(result_no_links)), unescape(result)
Loading

0 comments on commit 62bdfa7

Please sign in to comment.