Skip to content

Commit 10d24ef

Browse files
authored
Merge pull request #765 from linode/dev
Release v5.57.0
2 parents 556685d + 91678ed commit 10d24ef

33 files changed

+1296
-400
lines changed

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ on:
2020
description: 'The number of the PR.'
2121
required: false
2222

23-
name: PR E2E Tests
23+
name: Integration Tests on Windows
2424

2525
jobs:
2626
integration-fork-windows:
@@ -65,9 +65,6 @@ jobs:
6565
with:
6666
python-version: '3.x'
6767

68-
- name: Install Python deps
69-
run: pip install .[obj,dev]
70-
7168
- name: Install the CLI
7269
run: make install
7370
env:

.github/workflows/e2e-suite.yml

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Integration Tests
1+
name: Integration Tests on Linux
22

33
on:
44
workflow_dispatch:
@@ -97,9 +97,6 @@ jobs:
9797
env:
9898
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9999

100-
- name: Update system packages
101-
run: sudo apt-get update -y
102-
103100
- name: Setup Python
104101
uses: actions/setup-python@v5
105102
with:
@@ -235,6 +232,8 @@ jobs:
235232
runs-on: ubuntu-latest
236233
needs: [integration_tests]
237234
if: always() && github.repository == 'linode/linode-cli' # Run even if integration tests fail and only on main repository
235+
outputs:
236+
summary: ${{ steps.set-test-summary.outputs.summary }}
238237

239238
steps:
240239
- name: Checkout code
@@ -275,14 +274,26 @@ jobs:
275274
LINODE_CLI_OBJ_ACCESS_KEY: ${{ secrets.LINODE_CLI_OBJ_ACCESS_KEY }}
276275
LINODE_CLI_OBJ_SECRET_KEY: ${{ secrets.LINODE_CLI_OBJ_SECRET_KEY }}
277276

277+
- name: Generate test summary and save to output
278+
id: set-test-summary
279+
run: |
280+
filename=$(ls | grep -E '^[0-9]{12}_cli_test_report\.xml$')
281+
test_output=$(python3 e2e_scripts/tod_scripts/generate_test_summary.py "${filename}")
282+
{
283+
echo 'summary<<EOF'
284+
echo "$test_output"
285+
echo EOF
286+
} >> "$GITHUB_OUTPUT"
287+
278288
279289
notify-slack:
280290
runs-on: ubuntu-latest
281-
needs: [integration_tests]
291+
needs: [integration_tests, process-upload-report]
282292
if: ${{ (success() || failure()) && github.repository == 'linode/linode-cli' }} # Run even if integration tests fail and only on main repository
283293

284294
steps:
285295
- name: Notify Slack
296+
id: main_message
286297
uses: slackapi/slack-github-action@v2.0.0
287298
with:
288299
method: chat.postMessage
@@ -293,7 +304,7 @@ jobs:
293304
- type: section
294305
text:
295306
type: mrkdwn
296-
text: ":rocket: *${{ github.workflow }} Completed in: ${{ github.repository }}* :white_check_mark:"
307+
text: ":rocket: *${{ github.workflow }} Completed in: ${{ github.repository }}* ${{ needs.integration_tests.result == 'success' && ':white_check_mark:' || ':failed:' }}"
297308
- type: divider
298309
- type: section
299310
fields:
@@ -312,3 +323,14 @@ jobs:
312323
elements:
313324
- type: mrkdwn
314325
text: "Triggered by: :bust_in_silhouette: `${{ github.actor }}`"
326+
327+
- name: Test summary thread
328+
if: success()
329+
uses: slackapi/slack-github-action@v2.0.0
330+
with:
331+
method: chat.postMessage
332+
token: ${{ secrets.SLACK_BOT_TOKEN }}
333+
payload: |
334+
channel: ${{ secrets.SLACK_CHANNEL_ID }}
335+
thread_ts: "${{ steps.main_message.outputs.ts }}"
336+
text: "${{ needs.process-upload-report.outputs.summary }}"

.github/workflows/labeler.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
uses: actions/checkout@v4
2222
-
2323
name: Run Labeler
24-
uses: crazy-max/ghaction-github-labeler@b54af0c25861143e7c8813d7cbbf46d2c341680c
24+
uses: crazy-max/ghaction-github-labeler@24d110aa46a59976b8a7f35518cb7f14f434c916
2525
with:
2626
github-token: ${{ secrets.GITHUB_TOKEN }}
2727
yaml-file: .github/labels.yml

.github/workflows/release.yml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ jobs:
3939
run: make requirements
4040

4141
- name: Set up QEMU
42-
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # pin@v3.3.0
42+
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # pin@v3.6.0
4343

4444
- name: Set up Docker Buildx
45-
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # pin@v3.8.0
45+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # pin@v3.10.0
4646

4747
- name: Login to Docker Hub
48-
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3.3.0
48+
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # pin@v3.4.0
4949
with:
5050
username: ${{ secrets.DOCKERHUB_USERNAME }}
5151
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -67,7 +67,7 @@ jobs:
6767
result-encoding: string
6868

6969
- name: Build and push to DockerHub
70-
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # pin@v6.13.0
70+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # pin@v6.15.0
7171
with:
7272
context: .
7373
file: Dockerfile
@@ -79,7 +79,11 @@ jobs:
7979
github_token=${{ secrets.GITHUB_TOKEN }}
8080
8181
pypi-release:
82+
permissions:
83+
# IMPORTANT: this permission is mandatory for trusted publishing
84+
id-token: write
8285
runs-on: ubuntu-latest
86+
environment: pypi-release
8387
steps:
8488
- name: Checkout
8589
uses: actions/checkout@v4
@@ -103,5 +107,3 @@ jobs:
103107

104108
- name: Publish the release artifacts to PyPI
105109
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # pin@release/v1.12.4
106-
with:
107-
password: ${{ secrets.PYPI_API_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ test/.env
1414
MANIFEST
1515
venv
1616
openapi*.yaml
17+
openapi*.json

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ VERSION_FILE := ./linodecli/version.py
1212
VERSION_MODULE_DOCSTRING ?= \"\"\"\nThe version of the Linode CLI.\n\"\"\"\n\n
1313
LINODE_CLI_VERSION ?= "0.0.0.dev"
1414

15+
BAKE_FLAGS := --debug
16+
1517
.PHONY: install
1618
install: check-prerequisites requirements build
1719
pip3 install --force dist/*.whl
@@ -21,7 +23,7 @@ bake: clean
2123
ifeq ($(SKIP_BAKE), 1)
2224
@echo Skipping bake stage
2325
else
24-
python3 -m linodecli bake ${SPEC} --skip-config
26+
python3 -m linodecli bake ${SPEC} --skip-config $(BAKE_FLAGS)
2527
cp data-3 linodecli/
2628
endif
2729

linodecli/__init__.py

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""
55

66
import argparse
7+
import logging
78
import os
89
import sys
910
from importlib.metadata import version
@@ -38,12 +39,14 @@
3839

3940
TEST_MODE = os.getenv("LINODE_CLI_TEST_MODE") == "1"
4041

42+
# Configure the `logging` package log level depending on the --debug flag.
43+
logging.basicConfig(
44+
level=logging.DEBUG if "--debug" in argv else logging.WARNING,
45+
)
46+
4147
# if any of these arguments are given, we don't need to prompt for configuration
4248
skip_config = (
43-
any(
44-
c in argv
45-
for c in ["--skip-config", "--help", "--version", "completion"]
46-
)
49+
any(c in argv for c in ["--skip-config", "--version", "completion"])
4750
or TEST_MODE
4851
)
4952

@@ -104,6 +107,43 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
104107
# if not spec was found and we weren't baking, we're doomed
105108
sys.exit(ExitCodes.ARGUMENT_ERROR)
106109

110+
if parsed.command in ("set-custom-alias", "remove-custom-alias"):
111+
if not parsed.alias_command or not parsed.alias:
112+
print(
113+
"Both --alias-command and --alias must be provided.",
114+
file=sys.stderr,
115+
)
116+
sys.exit(ExitCodes.ARGUMENT_ERROR)
117+
118+
command = parsed.alias_command
119+
alias = parsed.alias
120+
121+
if command not in cli.ops:
122+
print(
123+
f"Error: '{command}' is not a valid command.", file=sys.stderr
124+
)
125+
sys.exit(ExitCodes.ARGUMENT_ERROR)
126+
127+
if parsed.command == "set-custom-alias":
128+
if (alias, command) not in cli.config.get_custom_aliases().items():
129+
cli.config.set_custom_alias(alias, command)
130+
print(f"Custom alias '{alias}' set for command '{command}'")
131+
else:
132+
print(
133+
f"Custom alias '{alias}' already set for command '{command}'"
134+
)
135+
136+
if parsed.command == "remove-custom-alias":
137+
if (alias, command) in cli.config.get_custom_aliases().items():
138+
cli.config.remove_custom_alias(alias, command)
139+
print(f"Custom alias '{alias}' removed for command '{command}'")
140+
else:
141+
print(
142+
f"Custom alias '{alias}' does not exist for command '{command}'"
143+
)
144+
145+
sys.exit(ExitCodes.SUCCESS)
146+
107147
if parsed.command == "register-plugin":
108148
if parsed.action is None:
109149
print("register-plugin requires a module name!", file=sys.stderr)
@@ -207,28 +247,36 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
207247
plugin_args.remove(parsed.command) # don't include the plugin name
208248
plugins.invoke(parsed.command, plugin_args, context)
209249
sys.exit(ExitCodes.SUCCESS)
210-
211250
# unknown commands
212251
if (
213252
parsed.command not in cli.ops
214253
and parsed.command not in plugins.available(cli.config)
215254
and parsed.command not in HELP_TOPICS
255+
and parsed.command not in cli.config.get_custom_aliases().keys()
216256
):
217257
print(f"Unrecognized command {parsed.command}", file=sys.stderr)
218258
sys.exit(ExitCodes.UNRECOGNIZED_COMMAND)
219259

220260
# handle a help for a command - either --help or no action triggers this
221-
if (
222-
parsed.command is not None
223-
and parsed.action is None
224-
and parsed.command in cli.ops
225-
):
226-
print_help_command_actions(cli.ops, parsed.command)
227-
sys.exit(ExitCodes.SUCCESS)
261+
if parsed.command is not None and parsed.action is None:
262+
if parsed.command in cli.ops:
263+
print_help_command_actions(cli.ops, parsed.command)
264+
sys.exit(ExitCodes.SUCCESS)
265+
if parsed.command in cli.config.get_custom_aliases().keys():
266+
print_help_command_actions(
267+
cli.ops, cli.config.get_custom_aliases()[parsed.command]
268+
)
228269

229270
if parsed.command is not None and parsed.action is not None:
230271
if parsed.help:
231-
print_help_action(cli, parsed.command, parsed.action)
272+
if parsed.command in cli.config.get_custom_aliases().keys():
273+
print_help_action(
274+
cli,
275+
cli.config.get_custom_aliases()[parsed.command],
276+
parsed.action,
277+
)
278+
else:
279+
print_help_action(cli, parsed.command, parsed.action)
232280
sys.exit(ExitCodes.SUCCESS)
233281

234282
cli.handle_command(parsed.command, parsed.action, args)

0 commit comments

Comments
 (0)