Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/automation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Automation Guide

`gcalcli` provides features specifically designed for automation scripts and agents.

## Non-Interactive Mode support (CI/CD)

Use automation flags to prevent the tool from pausing for user input:

- `--yes`, `--force`, `--no-prompt`: Automatically answer "yes" to confirmation prompts (like delete).
- `--noprompt` (specific to `add`): Skips prompting for missing fields during event creation.
33 changes: 30 additions & 3 deletions gcalcli/argparsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,30 @@ def get_search_parser():
return search_parser


def get_automation_parser():
# Flags for skipping confirmation prompts
automation_parser = argparse.ArgumentParser(add_help=False)
automation_parser.add_argument(
'--yes', '-y',
action='store_true',
dest='noconfirm',
help='Answer "yes" to all prompts (e.g. delete confirmation)'
)
automation_parser.add_argument(
'--force', '-f',
action='store_true',
dest='noconfirm',
help='Alias for --yes'
)
automation_parser.add_argument(
'--no-prompt',
action='store_true',
dest='noconfirm',
help='Alias for --yes'
)
return automation_parser


def handle_unparsed(unparsed, namespace):
# Attempt a reparse against the program options.
# Provides some robustness for misplaced global options
Expand Down Expand Up @@ -450,6 +474,9 @@ def get_argument_parser():

# tacks on search text
search_parser = get_search_parser()

# automation flags
automation_parser = get_automation_parser()

sub = parser.add_subparsers(
help='Invoking a subcommand with --help prints subcommand usage.',
Expand Down Expand Up @@ -496,13 +523,13 @@ def get_argument_parser():

delete = sub.add_parser(
'delete',
parents=[calendars_parser, output_parser, search_parser],
parents=[calendars_parser, output_parser, search_parser, automation_parser],
help='delete events from the calendar',
description='Case insensitive search for items to delete '
'interactively.',
)
delete.add_argument(
'--iamaexpert', action='store_true', help='Probably not'
'--iamaexpert', action='store_true', help='Legacy alias for --yes'
)

sub.add_parser(
Expand Down Expand Up @@ -656,7 +683,7 @@ def get_argument_parser():

_import = sub.add_parser(
'import',
parents=[calendar_parser, remind_parser],
parents=[calendar_parser, remind_parser, automation_parser],
help='import an ics/vcal file to a calendar',
description='Import from an ics/vcal file; a single --calendar '
'must be specified. Reads from stdin when no file argument is '
Expand Down
11 changes: 9 additions & 2 deletions gcalcli/gcal.py
Original file line number Diff line number Diff line change
Expand Up @@ -997,11 +997,18 @@ def _delete_event(self, event):
cal_id = event['gcalcli_cal']['id']
event_id = event['id']

if self.expert:
if self.expert or self.options.get('noconfirm'):
self.delete(cal_id, event_id)
self.printer.msg('Deleted!\n', 'red')
return

# Print "Safe Prompt" summary
time_str = event['s'].strftime('%Y-%m-%d %H:%M')
if is_all_day(event):
time_str = event['s'].strftime('%Y-%m-%d')

self.printer.msg(f'> Found Event: "{_valid_title(event).strip()}" ({time_str})\n', 'yellow')

self.printer.msg('Delete? [N]o [y]es [q]uit: ', 'magenta')
val = input()

Expand Down Expand Up @@ -1643,7 +1650,7 @@ def ImportICS(self, verbose=False, dump=False, reminders=None,

self._add_reminders(event.body, reminders)

if not verbose:
if not verbose or self.options.get('noconfirm'):
# Don't prompt, just assume user wants to import.
pass
else:
Expand Down