Exit code 1
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0 -- /home/david/projects/stirlingbridge/machine/.venv/bin/python
cachedir: .pytest_cache
rootdir: /home/david/projects/stirlingbridge/machine
configfile: pyproject.toml
collecting ... collected 4 items
tests/test_e2e.py::TestDropletLifecycle::test_create_and_list_and_destroy FAILED [ 25%]
=================================== FAILURES ===================================
____________ TestDropletLifecycle.test_create_and_list_and_destroy _____________
tests/test_e2e.py:156: in test_create_and_list_and_destroy
assert result.returncode == 0, f"create failed: {result.stderr}"
E AssertionError: create failed: Traceback (most recent call last):
E File "/home/david/projects/stirlingbridge/machine/.venv/bin/machine", line 10, in <module>
E sys.exit(main())
E ^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
E return self.main(*args, **kwargs)
E ^^^^^^^^^^^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1078, in main
E rv = self.invoke(ctx)
E ^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1688, in invoke
E return _process_result(sub_ctx.command.invoke(sub_ctx))
E ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
E return ctx.invoke(self.callback, **ctx.params)
E ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 783, in invoke
E return __callback(*args, **kwargs)
E ^^^^^^^^^^^^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/decorators.py", line 33, in new_func
E return f(get_current_context(), *args, **kwargs)
E ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/machine/subcommands/create.py", line 115, in command
E project.assign_resource([f"do:droplet:{droplet.id}"])
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/digitalocean/Project.py", line 141, in assign_resource
E return self.get_data("projects/%s/resources" % self.id, type=POST, params=data)
E ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/digitalocean/baseapi.py", line 233, in get_data
E raise DataReadError(msg)
E digitalocean.DataReadError: You are not authorized to perform this operation
E
E assert 1 == 0
E + where 1 = CompletedProcess(args=['uv', 'run', 'machine', '--config-file', '/tmp/pytest-of-david/pytest-5/e2e0/config.yml', '--session-id', 'db439ab2', 'create', '--name', 'e2etest-9f0e17af', '--no-initialize', '--wait-for-ip'], returncode=1, stdout='New droplet created with id: 558332018\n', stderr='Traceback (most recent call last):\n File "/home/david/projects/stirlingbridge/machine/.venv/bin/machine", line 10, in <module>\n sys.exit(main())\n ^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1157, in __call__\n return self.main(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1078, in main\n rv = self.invoke(ctx)\n ^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 1688, in invoke\n return _process_result(sub_ctx.command.invoke(sub_ctx))\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", lin...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/core.py", line 783, in invoke\n return __callback(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/click/decorators.py", line 33, in new_func\n return f(get_current_context(), *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/machine/subcommands/create.py", line 115, in command\n project.assign_resource([f"do:droplet:{droplet.id}"])\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/digitalocean/Project.py", line 141, in assign_resource\n return self.get_data("projects/%s/resources" % self.id, type=POST, params=data)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/david/projects/stirlingbridge/machine/.venv/lib/python3.12/site-packages/digitalocean/baseapi.py", line 233, in get_data\n raise DataReadError(msg)\ndigitalocean.DataReadError: You are not authorized to perform this operation\n').returncode
=========================== short test summary info ============================
FAILED tests/test_e2e.py::TestDropletLifecycle::test_create_and_list_and_destroy
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 4.68s ===============================Progress — the droplet was successfully created (id: 558332018), but it failed at create.py:115 when trying to assign the droplet to a project. The error is You are not authorized to perform this operation on the project resource assignment.
The token still seems to be missing project-related permissions. Note that the droplet was created but not cleaned up since the test failed before recording the ID. You may want to manually destroy droplet 558332018.
The token needs the project:read and project:update permissions (or a full-access token) to assign resources to projects.
Sounds good. You'll also want to clean up the orphaned droplet 558332018 that was created during that last run.