Skip to content

s3stream: follow CI logs from the CLI#9274

Open
allisonkarlitskaya wants to merge 3 commits into
mainfrom
s3stream
Open

s3stream: follow CI logs from the CLI#9274
allisonkarlitskaya wants to merge 3 commits into
mainfrom
s3stream

Conversation

@allisonkarlitskaya

Copy link
Copy Markdown
Member

This lets you get the raw log from a complete or in-progress CI run and includes a --follow option which exits when the job completes.

Comment thread s3stream
)
bytes_received += len(data)
yield data
chunk_start = chunk_end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This assumes that the fetch call above always returns the full chunk, no? I.e., that bytes_received == chunk_end - chunk_start.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I reworked this a bit, but the general logic here is: we trust that urllib does what we asked it or throws an error. In the event of an incomplete read, we expect to hear about that...

Comment thread s3stream
except urllib.error.HTTPError as exc:
# S3 returns 403 for missing objects in some bucket configurations
if exc.code in (403, 404):
break

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this break the while loop or just the try?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

break doesn't interact with try in any way...

Comment thread s3stream

time.sleep(10)

# Streaming is over (or never started) — fetch the (remaining) final log

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So the break above gets us here when .chunks doesn't exist?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

exactly.

mvollmer
mvollmer previously approved these changes Jul 14, 2026

@mvollmer mvollmer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

fetch_log was difficult to follow, but I have no good ideas for how to make it clearer.

@Venefilyn Venefilyn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems fine but you can also provide log.html and then it just outputs the HTML, which seems unintended. Would be nice for it to take the log.html URL as well and try the log URL itself

That way you can just copy the link from a PR without having to change it

@tomasmatus tomasmatus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the docs! It is much clearer to me how it works now

Comment thread lib/aio/s3streamer.py
# The entire protocol is bytes-oriented: chunk sizes in the manifest are
# byte counts, Range request offsets are byte offsets, and chunk filenames
# encode byte ranges. Although character offsets are never used for
# anything, the content is assumed to be UTF-8 text. The server

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

here you promise UTF-8 in the entire protocol but

self.destination.write('log.chunks', json.dumps(chunk_sizes).encode('ascii'))

:)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ascii is utf8 :)

@allisonkarlitskaya allisonkarlitskaya left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The removal of support for servers without range requests was a mistake because we suggest python3 -m http.server for use with our local log driver and.... it doesn't support range requests.

@allisonkarlitskaya
allisonkarlitskaya force-pushed the s3stream branch 2 times, most recently from 43a31fe to aed44c8 Compare July 16, 2026 10:56
This lets you get the raw log from a complete or in-progress CI run and
includes a `--follow` option which exits when the job completes.
s3streamer is effectively a mini protocol that a client and a server
speak over S3.  There are a few subtle points about the implementation
that are important to get straight, so spell them out explicitly.

Claude wrote a lot of the text here, but with a great deal of guidance
and manual editing.

Change to the SPDX header format while we're at it.
On the basis of the origin of the strings in question, it's probably
currently impossible for the `data: str` that we pass to s3streamer to
contain surrogates, but if it does, `.encode()` will explode.

Let's be a bit more gentle about this and replace with `�`.
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.

4 participants