Skip to content

Commit 700b935

Browse files
Merge pull request #651 from linode/dev
v5.52.0
2 parents e99d833 + 524fa64 commit 700b935

38 files changed

+789
-145
lines changed

.github/workflows/e2e-suite.yml

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ on:
2323
- dev
2424

2525
jobs:
26-
integration-tests:
26+
integration_tests:
2727
name: Run integration tests on Ubuntu
2828
runs-on: ubuntu-latest
2929
if: github.event_name == 'workflow_dispatch' && inputs.sha != '' || github.event_name == 'push' || github.event_name == 'pull_request'
@@ -167,3 +167,69 @@ jobs:
167167
conclusion: process.env.conclusion
168168
});
169169
return result;
170+
171+
notify-slack:
172+
runs-on: ubuntu-latest
173+
needs: [integration_tests]
174+
if: always() && github.repository == 'linode/linode-cli' # Run even if integration tests fail and only on main repository
175+
176+
steps:
177+
- name: Notify Slack
178+
uses: slackapi/slack-github-action@v1.27.0
179+
with:
180+
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
181+
payload: |
182+
{
183+
"blocks": [
184+
{
185+
"type": "section",
186+
"text": {
187+
"type": "mrkdwn",
188+
"text": ":rocket: *${{ github.workflow }} Completed in: ${{ github.repository }}* :white_check_mark:"
189+
}
190+
},
191+
{
192+
"type": "divider"
193+
},
194+
{
195+
"type": "section",
196+
"fields": [
197+
{
198+
"type": "mrkdwn",
199+
"text": "*Build Result:*\n${{ steps.integration_tests.outcome == 'success' && ':large_green_circle: Build Passed' || ':red_circle: Build Failed' }}"
200+
},
201+
{
202+
"type": "mrkdwn",
203+
"text": "*Branch:*\n`${{ github.ref_name }}`"
204+
}
205+
]
206+
},
207+
{
208+
"type": "section",
209+
"fields": [
210+
{
211+
"type": "mrkdwn",
212+
"text": "*Commit Hash:*\n<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>"
213+
},
214+
{
215+
"type": "mrkdwn",
216+
"text": "*Run URL:*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run Details>"
217+
}
218+
]
219+
},
220+
{
221+
"type": "divider"
222+
},
223+
{
224+
"type": "context",
225+
"elements": [
226+
{
227+
"type": "mrkdwn",
228+
"text": "Triggered by: :bust_in_silhouette: `${{ github.actor }}`"
229+
}
230+
]
231+
}
232+
]
233+
}
234+
env:
235+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

.github/workflows/nightly-smoke-tests.yml

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,25 @@ on:
44
schedule:
55
- cron: "0 0 * * *"
66
workflow_dispatch:
7+
inputs:
8+
sha:
9+
description: 'Commit SHA to test'
10+
required: false
11+
default: ''
12+
type: string
713

814
jobs:
915
smoke_tests:
16+
if: github.repository == 'linode/linode-cli' || github.event_name == 'workflow_dispatch'
1017
runs-on: ubuntu-latest
1118

1219
steps:
1320
- name: Checkout code
14-
uses: actions/checkout@v3
21+
uses: actions/checkout@v4
1522
with:
16-
ref: dev
23+
fetch-depth: 0
24+
submodules: 'recursive'
25+
ref: ${{ github.event.inputs.sha || github.ref }}
1726

1827
- name: Set up Python
1928
uses: actions/setup-python@v4
@@ -29,7 +38,69 @@ jobs:
2938
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3039

3140
- name: Run smoke tests
41+
id: smoke_tests
3242
run: |
3343
make smoketest
3444
env:
3545
LINODE_CLI_TOKEN: ${{ secrets.LINODE_TOKEN }}
46+
47+
- name: Notify Slack
48+
if: always() && github.repository == 'linode/linode-cli' # Run even if integration tests fail and only on main repository
49+
uses: slackapi/slack-github-action@v1.26.0
50+
with:
51+
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
52+
payload: |
53+
{
54+
"blocks": [
55+
{
56+
"type": "section",
57+
"text": {
58+
"type": "mrkdwn",
59+
"text": ":rocket: *${{ github.workflow }} Completed in: ${{ github.repository }}* :white_check_mark:"
60+
}
61+
},
62+
{
63+
"type": "divider"
64+
},
65+
{
66+
"type": "section",
67+
"fields": [
68+
{
69+
"type": "mrkdwn",
70+
"text": "*Build Result:*\n${{ steps.smoke_tests.outcome == 'success' && ':large_green_circle: Build Passed' || ':red_circle: Build Failed' }}"
71+
},
72+
{
73+
"type": "mrkdwn",
74+
"text": "*Branch:*\n`${{ github.ref_name }}`"
75+
}
76+
]
77+
},
78+
{
79+
"type": "section",
80+
"fields": [
81+
{
82+
"type": "mrkdwn",
83+
"text": "*Commit Hash:*\n<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>"
84+
},
85+
{
86+
"type": "mrkdwn",
87+
"text": "*Run URL:*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run Details>"
88+
}
89+
]
90+
},
91+
{
92+
"type": "divider"
93+
},
94+
{
95+
"type": "context",
96+
"elements": [
97+
{
98+
"type": "mrkdwn",
99+
"text": "Triggered by: :bust_in_silhouette: `${{ github.actor }}`"
100+
}
101+
]
102+
}
103+
]
104+
}
105+
env:
106+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

.pylintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ disable=raw-checker-failed,
424424
duplicate-code,
425425
too-few-public-methods,
426426
too-many-instance-attributes,
427-
use-symbolic-message-instead
427+
use-symbolic-message-instead,
428+
too-many-positional-arguments
428429

429430
# Enable the message, report, category or checker with the given id(s). You can
430431
# either give multiple identifier separated by comma (,) or put this option

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ clean:
6666
rm -rf dist linode_cli.egg-info build
6767

6868
.PHONY: testunit
69-
testunit: export LINODE_CLI_TEST_MODE = 1
7069
testunit:
71-
pytest -v tests/unit
70+
@mkdir -p /tmp/linode/.config
71+
@orig_xdg_config_home=$${XDG_CONFIG_HOME:-}; \
72+
export LINODE_CLI_TEST_MODE=1 XDG_CONFIG_HOME=/tmp/linode/.config; \
73+
pytest -v tests/unit; \
74+
export XDG_CONFIG_HOME=$$orig_xdg_config_home
7275

7376
.PHONY: testint
7477
testint:

linodecli/__init__.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from .help_pages import (
2828
HELP_TOPICS,
2929
print_help_action,
30+
print_help_command_actions,
3031
print_help_commands,
3132
print_help_default,
3233
print_help_env_vars,
@@ -224,23 +225,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
224225
and parsed.action is None
225226
and parsed.command in cli.ops
226227
):
227-
print(f"linode-cli {parsed.command} [ACTION]")
228-
print()
229-
print("Available actions: ")
230-
231-
content = [
232-
[", ".join([action, *op.action_aliases]), op.summary]
233-
for action, op in cli.ops[parsed.command].items()
234-
]
235-
236-
table = Table(
237-
Column(header="action", no_wrap=True),
238-
Column(header="summary", style="cyan"),
239-
)
240-
for row in content:
241-
table.add_row(*row)
242-
243-
rprint(table)
228+
print_help_command_actions(cli.ops, parsed.command)
244229
sys.exit(ExitCodes.SUCCESS)
245230

246231
if parsed.command is not None and parsed.action is not None:

linodecli/api_request.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import itertools
66
import json
7+
import os
78
import sys
89
import time
910
from typing import Any, Iterable, List, Optional
@@ -373,8 +374,10 @@ def _attempt_warn_old_version(ctx, result):
373374
"with --suppress-warnings",
374375
file=sys.stderr,
375376
)
376-
377-
if new_version_exists:
377+
suppress_version_warning = ctx.config.get_bool(
378+
"suppress-version-warning"
379+
) or os.getenv("LINODE_CLI_SUPPRESS_VERSION_WARNING")
380+
if new_version_exists and not suppress_version_warning:
378381
print(
379382
f"The API responded with version {spec_version}, which is newer than "
380383
f"the CLI's version of {ctx.spec_version}. Please update the CLI to get "

linodecli/configuration/config.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,30 @@ def get_value(self, key: str) -> Optional[Any]:
186186

187187
return self.config.get(username, key)
188188

189+
def get_bool(self, key: str) -> bool:
190+
"""
191+
Retrieves and returns an existing config boolean for the current user. This
192+
is intended for plugins to use instead of having to deal with figuring out
193+
who the current user is when accessing their config.
194+
195+
.. warning::
196+
Plugins _MUST NOT_ set values for the user's config except through
197+
``plugin_set_value`` below.
198+
199+
:param key: The key to look up.
200+
:type key: str
201+
202+
:returns: The boolean for that key, or False if the key doesn't exist for the
203+
current user.
204+
:rtype: any
205+
"""
206+
username = self.username or self.default_username()
207+
208+
if not self.config.has_option(username, key):
209+
return False
210+
211+
return self.config.getboolean(username, key)
212+
189213
# plugin methods - these are intended for plugins to utilize to store their
190214
# own persistent config information
191215
def plugin_set_value(self, key: str, value: Any):
@@ -449,6 +473,9 @@ def configure(
449473
if _bool_input("Configure a custom API target?", default=False):
450474
self._configure_api_target(config)
451475

476+
if _bool_input("Suppress API Version Warnings?", default=False):
477+
config["suppress-version-warning"] = "true"
478+
452479
# save off the new configuration
453480
if username != "DEFAULT" and not self.config.has_section(username):
454481
self.config.add_section(username)

linodecli/help_pages.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
help pages.
44
"""
55

6+
import sys
67
import textwrap
78
from collections import defaultdict
8-
from typing import List, Optional
9+
from typing import Dict, List, Optional
910

1011
from rich import box
1112
from rich import print as rprint
1213
from rich.console import Console
1314
from rich.padding import Padding
14-
from rich.table import Table
15+
from rich.table import Column, Table
1516
from rich.text import Text
1617

1718
from linodecli import plugins
@@ -140,6 +141,36 @@ def print_help_default():
140141
)
141142

142143

144+
def print_help_command_actions(
145+
ops: Dict[str, Dict[str, OpenAPIOperation]],
146+
command: Optional[str],
147+
file=sys.stdout,
148+
):
149+
"""
150+
Prints the help page for a single command, including all actions
151+
under the given command.
152+
153+
:param ops: A dictionary mapping CLI commands -> actions -> operations.
154+
:param command: The command to print the help page for.
155+
"""
156+
157+
print(f"linode-cli {command} [ACTION]\n\nAvailable actions: ", file=file)
158+
159+
content = [
160+
[", ".join([action, *op.action_aliases]), op.summary]
161+
for action, op in sorted(ops[command].items(), key=lambda v: v[0])
162+
]
163+
164+
table = Table(
165+
Column(header="action", no_wrap=True),
166+
Column(header="summary", style="cyan"),
167+
)
168+
for row in content:
169+
table.add_row(*row)
170+
171+
rprint(table, file=file)
172+
173+
143174
def print_help_action(
144175
cli: "CLI", command: Optional[str], action: Optional[str]
145176
):

0 commit comments

Comments
 (0)