Skip to content

Commit 9b43cf8

Browse files
Merge pull request #548 from linode/dev
Release v5.45.2
2 parents 506c011 + b9bba92 commit 9b43cf8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+698
-299
lines changed

.github/workflows/e2e-suite-pr-command.yml

Lines changed: 0 additions & 19 deletions
This file was deleted.

.github/workflows/e2e-suite-pr.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ on:
33
workflow_dispatch:
44
inputs:
55
test_path:
6-
description: 'Test path to be tested: e.g. integration/cli'
6+
description: "The path from 'test/integration' to the target to be tested, e.g. 'cli'"
77
required: false
88
sha:
99
description: 'The hash value of the commit.'
@@ -30,7 +30,7 @@ jobs:
3030

3131
# Check out merge commit
3232
- name: Checkout PR
33-
uses: actions/checkout@v3
33+
uses: actions/checkout@v4
3434
with:
3535
ref: ${{ inputs.sha }}
3636

@@ -56,13 +56,12 @@ jobs:
5656
owner: ${{ github.event.repository.owner.login }}
5757
repo: ${{ github.event.repository.name }}
5858
pr_num: ${{ fromJSON(inputs.pull_request_number) }}
59+
env:
60+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5961

6062
- name: Update system packages
6163
run: sudo apt-get update -y
6264

63-
- name: Install system deps
64-
run: sudo apt-get install -y build-essential
65-
6665
- name: Setup Python
6766
uses: actions/setup-python@v4
6867
with:
@@ -124,7 +123,7 @@ jobs:
124123

125124
# Check out merge commit
126125
- name: Checkout PR
127-
uses: actions/checkout@v3
126+
uses: actions/checkout@v4
128127
with:
129128
ref: ${{ inputs.sha }}
130129

@@ -196,4 +195,4 @@ jobs:
196195
status: 'completed',
197196
conclusion: process.env.conclusion
198197
});
199-
return result;
198+
return result;

.github/workflows/e2e-suite.yml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ jobs:
99
integration-tests:
1010
name: Run integration tests
1111
runs-on: ubuntu-latest
12+
env:
13+
EXIT_STATUS: 0
1214
steps:
1315
- name: Clone Repository
1416
uses: actions/checkout@v3
@@ -39,9 +41,8 @@ jobs:
3941
run: |
4042
timestamp=$(date +'%Y%m%d%H%M')
4143
report_filename="${timestamp}_cli_test_report.xml"
42-
status=0
4344
if ! pytest tests/integration --disable-warnings --junitxml="${report_filename}"; then
44-
echo "Tests failed, but attempting to upload results anyway"
45+
echo "EXIT_STATUS=1" >> $GITHUB_ENV
4546
fi
4647
env:
4748
LINODE_CLI_TOKEN: ${{ secrets.LINODE_TOKEN }}
@@ -67,4 +68,13 @@ jobs:
6768
env:
6869
LINODE_CLI_TOKEN: ${{ secrets.SHARED_DX_TOKEN }}
6970
LINODE_CLI_OBJ_ACCESS_KEY: ${{ secrets.LINODE_CLI_OBJ_ACCESS_KEY }}
70-
LINODE_CLI_OBJ_SECRET_KEY: ${{ secrets.LINODE_CLI_OBJ_SECRET_KEY }}
71+
LINODE_CLI_OBJ_SECRET_KEY: ${{ secrets.LINODE_CLI_OBJ_SECRET_KEY }}
72+
73+
- name: Test Execution Status Handler
74+
run: |
75+
if [[ "$EXIT_STATUS" != 0 ]]; then
76+
echo "Test execution contains failure(s)"
77+
exit $EXIT_STATUS
78+
else
79+
echo "Tests passed!"
80+
fi

.github/workflows/remote-release-trigger.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ jobs:
5656
5757
return "v" + cli_version_segments.join(".")
5858
59+
- name: Calculate the SHA of HEAD on the main branch
60+
id: calculate_head_sha
61+
run: echo "commit_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
62+
5963
- uses: rickstaa/action-create-tag@84c90e6ba79b47b5147dcb11ff25d6a0e06238ba # pin@v1
6064
with:
6165
tag: ${{ steps.calculate_version.outputs.result }}
66+
commit_sha: ${{ steps.calculate_head_sha.outputs.commit_sha }}
6267

6368
- name: Release
6469
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # pin@v1

.pylintrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,8 @@ min-public-methods=2
307307
[EXCEPTIONS]
308308

309309
# Exceptions that will emit a warning when caught.
310-
overgeneral-exceptions=BaseException,
311-
Exception
310+
overgeneral-exceptions=builtins.BaseException,
311+
builtins.Exception
312312

313313

314314
[FORMAT]

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ endif
1818
install: check-prerequisites requirements build
1919
pip3 install --force dist/*.whl
2020

21-
.PHONY: build
22-
build: clean
21+
.PHONY: bake
22+
bake: clean
2323
python3 -m linodecli bake ${SPEC} --skip-config
2424
cp data-3 linodecli/
25+
26+
.PHONY: build
27+
build: clean bake
2528
python3 -m build --wheel --sdist
2629

2730
.PHONY: requirements

linodecli/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import argparse
77
import os
88
import sys
9+
from importlib.metadata import version
910
from sys import argv
1011

11-
import pkg_resources
1212
from rich import print as rprint
1313
from rich.table import Table
1414

@@ -30,7 +30,7 @@
3030

3131
# this might not be installed at the time of building
3232
try:
33-
VERSION = pkg_resources.require("linode-cli")[0].version
33+
VERSION = version("linode-cli")
3434
except:
3535
VERSION = "building"
3636

linodecli/arg_helpers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,10 @@ def action_help(cli, command, action):
380380
if op.method in {"post", "put"} and arg.required
381381
else ""
382382
)
383-
print(f" --{arg.path}: {is_required}{arg.description}")
383+
nullable_fmt = " (nullable)" if arg.nullable else ""
384+
print(
385+
f" --{arg.path}: {is_required}{arg.description}{nullable_fmt}"
386+
)
384387

385388

386389
def bake_command(cli, spec_loc):

linodecli/baked/operation.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from os import environ, path
1212
from typing import List, Tuple
1313

14+
from openapi3.paths import Operation
15+
1416
from linodecli.baked.request import OpenAPIFilteringRequest, OpenAPIRequest
1517
from linodecli.baked.response import OpenAPIResponse
1618
from linodecli.overrides import OUTPUT_OVERRIDES
@@ -76,6 +78,27 @@ def type_func(value):
7678
return type_func
7779

7880

81+
class ArrayAction(argparse.Action):
82+
"""
83+
This action is intended to be used only with array arguments.
84+
This purpose of this action is to allow users to specify explicitly
85+
empty lists using a singular "[]" argument value.
86+
"""
87+
88+
def __call__(self, parser, namespace, values, option_string=None):
89+
if getattr(namespace, self.dest) is None:
90+
setattr(namespace, self.dest, [])
91+
92+
output_list = getattr(namespace, self.dest)
93+
94+
# If the output list is empty and the user specifies a []
95+
# argument, keep the list empty
96+
if values == "[]" and len(output_list) < 1:
97+
return
98+
99+
output_list.append(values)
100+
101+
79102
class ListArgumentAction(argparse.Action):
80103
"""
81104
This action is intended to be used only with list arguments.
@@ -212,7 +235,7 @@ class OpenAPIOperation:
212235
This is the class that should be pickled when building the CLI.
213236
"""
214237

215-
def __init__(self, command, operation, method, params):
238+
def __init__(self, command, operation: Operation, method, params):
216239
"""
217240
Wraps an openapi3.Operation object and handles pulling out values relevant
218241
to the Linode CLI.
@@ -380,7 +403,7 @@ def _add_args_post_put(self, parser) -> List[Tuple[str, str]]:
380403
parser.add_argument(
381404
"--" + arg.path,
382405
metavar=arg.name,
383-
action="append",
406+
action=ArrayAction,
384407
type=arg_type_handler,
385408
)
386409
elif arg.list_item:

linodecli/baked/response.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""
22
Converting the processed OpenAPI Responses into something the CLI can work with
33
"""
4+
from openapi3.paths import MediaType
5+
46
from .colors import colorize_string
57

68

@@ -159,26 +161,35 @@ def _parse_response_model(schema, prefix=None, nested_list_depth=0):
159161
:returns: The list of parsed OpenAPIResponseAttr objects representing this schema
160162
:rtype: List[OpenAPIResponseAttr]
161163
"""
162-
attrs = []
163164

164-
if schema.properties is not None:
165-
for k, v in schema.properties.items():
166-
pref = prefix + "." + k if prefix else k
167-
168-
if v.type == "object":
169-
attrs += _parse_response_model(v, prefix=pref)
170-
elif v.type == "array" and v.items.type == "object":
171-
attrs += _parse_response_model(
172-
v.items,
173-
prefix=pref,
174-
nested_list_depth=nested_list_depth + 1,
175-
)
176-
else:
177-
attrs.append(
178-
OpenAPIResponseAttr(
179-
k, v, prefix=prefix, nested_list_depth=nested_list_depth
180-
)
165+
if schema.type == "array":
166+
return _parse_response_model(
167+
schema.items,
168+
prefix=prefix,
169+
nested_list_depth=nested_list_depth,
170+
)
171+
172+
attrs = []
173+
if schema.properties is None:
174+
return attrs
175+
176+
for k, v in schema.properties.items():
177+
pref = prefix + "." + k if prefix else k
178+
179+
if v.type == "object":
180+
attrs += _parse_response_model(v, prefix=pref)
181+
elif v.type == "array" and v.items.type == "object":
182+
attrs += _parse_response_model(
183+
v.items,
184+
prefix=pref,
185+
nested_list_depth=nested_list_depth + 1,
186+
)
187+
else:
188+
attrs.append(
189+
OpenAPIResponseAttr(
190+
k, v, prefix=prefix, nested_list_depth=nested_list_depth
181191
)
192+
)
182193

183194
return attrs
184195

@@ -189,7 +200,7 @@ class OpenAPIResponse:
189200
responses section of an OpenAPI Operation
190201
"""
191202

192-
def __init__(self, response):
203+
def __init__(self, response: MediaType):
193204
"""
194205
:param response: The response's MediaType object in the OpenAPI spec,
195206
corresponding to the application/json response type
@@ -228,7 +239,9 @@ def fix_json(self, json):
228239
# Needs to go last to handle custom schemas
229240
if "pages" in json:
230241
return json["data"]
231-
return [json]
242+
if not isinstance(json, list):
243+
json = [json]
244+
return json
232245

233246
def _fix_json_rows(self, json):
234247
"""

0 commit comments

Comments
 (0)