Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make odk.py seed more robust #1097

Merged
merged 3 commits into from
Aug 23, 2024
Merged

Make odk.py seed more robust #1097

merged 3 commits into from
Aug 23, 2024

Conversation

gouttegd
Copy link
Contributor

The seed command of the odk.py script is quite fragile, in that it will easily and loudly crash out when it used incorrectly.

A) Called with no positional arguments (odk.py seed):

This causes a crash because the repo variable is then set to None, while the Jinja template expects a string (or at least something that has a upper() method):

Traceback (most recent call last):
  File "/tools/odk.py", line 1112, in <module>
    cli()
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tools/odk.py", line 1041, in seed
    tgts += unpack_files(tdir, mg.generate(srcf))
                               ^^^^^^^^^^^^^^^^^
  File "/tools/odk.py", line 800, in generate
    return template.render( project = self.context.project, env = {"ODK_VERSION": os.getenv("ODK_VERSION")})
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.12/dist-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 339, in top-level template code
  File "/usr/local/lib/python3.12/dist-packages/jinja2/utils.py", line 83, in from_obj
    if hasattr(obj, "jinja_pass_arg"):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
jinja2.exceptions.UndefinedError: 'None' has no attribute 'upper'

This PR fixes that by setting the repo variable to noname rather than None, resulting in the seeding process successfully creating a noname repository.

B) Called with too many positional arguments (odk.py seed repo1 repo2)

Only one positional argument is expected. The error condition is correctly caught early, but it still yields an unhelpful stack trace:

Traceback (most recent call last):
  File "/tools/odk.py", line 1112, in <module>
    cli()
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tools/odk.py", line 996, in seed
    raise Exception('max one repo; current={}'.format(repo))
Exception: max one repo; current=('a', 'b')

We fix that here by raising a ClickException rather than a raw Exception; Click can intercept those and display only the error message rather than a full stack trace.

C) Missing Git username and/or email

Unless --skipgit is used, the seeding process needs a Git username and email to pass to Git to create the first commit once the repository is initialised. If for some reason we don’t have a username and/or an email address, this will cause an uncaught exception quite late in the seedingprocess, after all the files have been generated:

ERROR:root:Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "[email protected]"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'odkuser@b382b06553bd.(none)')

Traceback (most recent call last):
  File "/tools/odk.py", line 1112, in <module>
    cli()
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tools/odk.py", line 1076, in seed
    runcmd("cd {dir}/src/ontology && make && git commit -m 'initial commit' -a && git branch -M {branch} && make prepare_initial_release && git commit -m 'first release'".format(dir=outdir, branch=project.git_main_branch))
  File "/tools/odk.py", line 1106, in runcmd
    raise Exception('Failed: {}'.format(cmd))
Exception: Failed: cd target/noname/src/ontology && make && git commit -m 'initial commit' -a && git branch -M main && make prepare_initial_release && git commit -m 'first release'

That error condition should instead be caught early in the script, before even attempting to generate anything. This is what we do here.

Calling `odk.py seed` without any argument results in a crash because
the `repo` variable (supposed to hold the name of the repository) is set
to None, which is not expected by the Jinja template (it expects a
string).

When no positional arguments are specified, we set the `repo` variable
to `noname` instead, thereby allowing the creation of a full repository
with a dummy name instead of causing an error.
When seeding, and unless the --skipgit option has been used, we need a
username and email address to pass to Git. If we don't have those, the
seeding process will crash at the very end, after all files have been
generated.

Since the Git username and email are necessary, we should detect whether
we have them at the very beginning, and exit cleanly (with a message
telling the user what they need to to) as soon as possible, without even
initiating a process that is bound to fail.
The seed command expects only one positional arguments. If we got more
than one, we should exit with a clean error message, instead of crashing
with an uncaught exception and the associated stacktrace.
@gouttegd gouttegd self-assigned this Aug 23, 2024
@gouttegd gouttegd requested a review from matentzn August 23, 2024 16:04
Copy link
Contributor

@matentzn matentzn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Looks good!

@gouttegd gouttegd merged commit 06a0d2e into master Aug 23, 2024
1 check passed
@gouttegd gouttegd deleted the consolidate-odk-script branch August 23, 2024 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants