-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
feat(preprod): Add preprod artifact upload endpoint #92528
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
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅ ✅ All tests successful. No failed tests found. Additional details and impacted files@@ Coverage Diff @@
## master #92528 +/- ##
==========================================
+ Coverage 87.90% 87.91% +0.01%
==========================================
Files 10251 10255 +4
Lines 587928 588565 +637
Branches 22830 22830
==========================================
+ Hits 516792 517422 +630
- Misses 70690 70697 +7
Partials 446 446 |
"type": "array", | ||
"items": {"type": "string", "pattern": "^[0-9a-f]{40}$"}, | ||
}, | ||
# Optional metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this where we might need Git sha or other git info?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, after writing this doc, I think it's most likely that we'd just include the git info in the request body
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did we end up creating a 'prepod' app folder? is there any reason why the endpoint and task can't live there instead of the catchall folders?
good catch, I can move the endpoint into it. The task file already existed though (just adding a method into it), so I'll plan to leave it as is assuming that's kosher 🙏 |
ah yup that makes sense. thanks! also feel free to define your own urls file and import them into the main one like here:
|
104af77
to
9a61bbf
Compare
|
||
@region_silo_endpoint | ||
class ProjectPreprodArtifactAssembleEndpoint(ProjectEndpoint): | ||
owner = ApiOwner.OWNERS_INGEST |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be for our team.
"file_name": data.get("file_name"), | ||
"sha": data.get("sha"), | ||
"build_configuration": data.get("build_configuration"), | ||
"extras": data.get("extras"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extras
shouldn't be part of the external API, these are more for our own internal use. We had a few use-cases in Emerge that were locked down to org42, but let's try to avoid that here if possible for as long as we can.
src/sentry/tasks/assemble.py
Outdated
# 4. Update state to PROCESSED when done (also update the date_built value to reflect when the artifact was built, among other fields) | ||
|
||
except Exception as e: | ||
logger.exception("Failed to assemble preprod artifact") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you record the project/org?
"project_id": project.id, | ||
"checksum": checksum, | ||
"chunks": chunks, | ||
"file_name": data.get("file_name"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we removed filename in our API a while back, do you think the UUID is fine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hah, it's still in our docs. yea I talked w hector about this and neither of us felt strongly. We can just auto-gen a file name and remove this param 👍
"checksum": checksum, | ||
"chunks": chunks, | ||
"file_name": data.get("file_name"), | ||
"sha": data.get("sha"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: since this assemble api is doing some checksum stuff, maybe this should be git_sha
?
if state == ChunkFileState.OK: | ||
return Response({"state": state, "detail": detail, "missingChunks": []}) | ||
elif state is not None: | ||
return Response({"state": state, "detail": detail, "missingChunks": []}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The if
and elif
branches are the same, so this should be equivalent to
if state == ChunkFileState.OK: | |
return Response({"state": state, "detail": detail, "missingChunks": []}) | |
elif state is not None: | |
return Response({"state": state, "detail": detail, "missingChunks": []}) | |
if state is not None: | |
return Response({"state": state, "detail": detail, "missingChunks": []}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not commenting on the Emerge specific code. I'll let your team decide what Emerge-specific code should do and if its properly covered. Unfortunately I'm not on any of the teams which are required reviewers. @wedamija was interested in reviewing some of the Emerge code and probably will get you past the review block.
General comments. You don't have to change anything. There are choices you can make. I know the endpoint file is taking inspiration from related files so the tests we have here reflect the choices made by others. But consider the lack of unit test coverage for this pull request. We require a database and Django to test your schema definition, for example. It might simplify your test setup to pull that out into a function. You can test it 100 different ways in a millisecond. I would say as much as possible make this endpoint unit testable. This is a core part of your workflows so having absolute certainty on how things behave would be important for me. Though you're welcome to make a choice that suits your needs.
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Outdated
Show resolved
Hide resolved
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Outdated
Show resolved
Hide resolved
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Outdated
Show resolved
Hide resolved
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Outdated
Show resolved
Hide resolved
src/sentry/tasks/assemble.py
Outdated
# where next set of changes will happen | ||
# TODO: Trigger artifact processing (size analysis, etc.) | ||
# This is where you'd add logic to: | ||
# 1. create_or_update a new row in the Commit table as well (once base_sha is added as a column to it) | ||
# 2. Detect artifact type (iOS/Android/etc.) | ||
# 3. Queue processing tasks | ||
# 4. Update state to PROCESSED when done (also update the date_built value to reflect when the artifact was built, among other fields) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be filled in before merging. Is this task useful on its own without the TODOs?
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Outdated
Show resolved
Hide resolved
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Outdated
Show resolved
Hide resolved
src/sentry/tasks/assemble.py
Outdated
# 3. Queue processing tasks | ||
# 4. Update state to PROCESSED when done (also update the date_built value to reflect when the artifact was built, among other fields) | ||
|
||
except Exception as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible this should be more specific. But logging out to Sentry (as you did below) makes this less of a concern than the previous comment on this.
src/sentry/preprod/tasks.py
Outdated
# Handle build configuration | ||
build_config = None | ||
if build_configuration: | ||
build_config, _ = PreprodBuildConfiguration.objects.get_or_create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other thing, this and PreprodArtifact
should likely be created together as part of a transaction.
ecb26de
to
13cf722
Compare
class ValidatePreprodArtifactSchemaTest(TestCase): | ||
"""Unit tests for schema validation function - no database required.""" | ||
|
||
def test_valid_minimal_schema(self): | ||
"""Test valid minimal schema passes validation.""" | ||
data = {"checksum": "a" * 40, "chunks": []} | ||
body = orjson.dumps(data) | ||
result, error = validate_preprod_artifact_schema(body) | ||
assert error is None | ||
assert result == data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For unit tests like these you don't need the class structure. You can just define a test:
def test_something():
...
The test_
prefix (in the tests directory) is a signal to pytest that it should execute that function. There's all sorts of other neat things you can do like bring in fixtures or parameterize your tests. For an example take a look at this test by Tony: https://github.com/getsentry/sentry/pull/92599/files#diff-76fbf98d7d80cafdea351cdb466743d2fa5b20afdb3951d4154406e111dc0805R1088-R1107
tests/sentry/preprod/api/endpoints/test_organization_preprod_artifact_assemble.py
Show resolved
Hide resolved
src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
Show resolved
Hide resolved
@getsentry/issue-workflow Ping. |
synced w malachi offline 👍 |
Suspect IssuesThis pull request was deployed and Sentry observed the following issues:
Did you find this useful? React with a 👍 or 👎 |
Upload endpoint described in the [emerge size integration proposal](https://www.notion.so/sentry/Emerge-Size-Integration-Technical-Proposal-1ec8b10e4b5d801d9bc4cf8c7cc5ad1b?d=1fa8b10e4b5d80df9ed5001c55e19b89#1fa8b10e4b5d80dba610cb7273434b0d) Most of the logic is pretty similar to the debug file and sourcemap upload endpoints in addition to the unit tests, I've manually tested uploading works via my [test sentry-cli branch](getsentry/sentry-cli#2533)
Adds the upload functionality to the new `mobile-app upload` command. Tested E2E with new API preprod/assemble endpoint added in getsentry/sentry#92528. Also added some basic tests to ensure a minimal APK is successfully uploaded and that it skips uploading if the server already has the chunks.
…eprod endpoints (#93825) #92528 (comment) as suggested by @JoshFerge a few weeks back. We're going to add a few more endpoints so it makes sense to have them all in the same self contained file
…eprod endpoints (#93825) #92528 (comment) as suggested by @JoshFerge a few weeks back. We're going to add a few more endpoints so it makes sense to have them all in the same self contained file
Upload endpoint described in the emerge size integration proposal
Most of the logic is pretty similar to the debug file and sourcemap upload endpoints
in addition to the unit tests, I've manually tested uploading works via my test sentry-cli branch