# Unstable sha256 sum for Artifact hosted in another Github repo

**URL:** <https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289>\
**Category:** Package Management\
**Created:** [August 1, 2025, 1:35pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289 "2025-08-01T13:35:08Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gregstrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregstrq/32/20620_2.png) [@Gregstrq](https://discourse.julialang.org/u/Gregstrq)\
**Post date:** [August 1, 2025, 1:35pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/1 "2025-08-01T13:35:08Z")

</div>

Hi, guys. I am trying to setup an Artifact and running into problems with sha256 checksum: every time it tries to download the file the checksum is different.

The tarball sits in another Github repository and I reference it using the permalink with the commit hash in the url. I have tried to repeatedly download it with `wget` and compute checksum, and every time the result is different. **Should not the sha256 be sensitive only to the contents of the file and not its metadata? Has anyone encountered such problem before?**

If you want to play around with it, here is the file [https://github.com/Gregstrq/Isotope-data/blob/9dd2180ba3bc6caf67063a59601af3e0960edbae/isotopes\_data.tar.gz](https://github.com/Gregstrq/Isotope-data/blob/9dd2180ba3bc6caf67063a59601af3e0960edbae/isotopes_data.tar.gz). I check the sha256 sum with

```julia-auto
using SHA
bytes2hex(open(sha256, "isotopes_data.tar.gz"))

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 1, 2025, 2:09pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/2 "2025-08-01T14:09:07Z")

</div>

Are you sure you’re actually downloading the _raw_ file? Or are you just downloading GitHub’s HTML page that displays it? That is, you want to use the URL of `https://github.com/Gregstrq/Isotope-data/raw/9dd2180ba3bc6caf67063a59601af3e0960edbae/isotopes_data.tar.gz` — note that that has a `/raw/` in there instead of the blob.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [August 1, 2025, 2:38pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/3 "2025-08-01T14:38:08Z")

</div>

> [@Gregstrq](#):
>
> Should not the sha256 be sensitive only to the contents of the file and not its metadata?

Depends on what you mean with content and metadata. The hash is computed from all the bytes in the file, regardless of their semantical meaning. It would be possible for GitHub to create a different file every time, differing on the MTIME field in the gzip header, but it’s highly unlikely that they would want to do that. @mbauman’s explanation is almost certainly correct.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 1, 2025, 2:44pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/4 "2025-08-01T14:44:19Z")

</div>

I do really like the pattern where artifacts are tagged and official GitHub release assets. It takes a bit to setup, but it has some very nice properties (like versioning, traceability, and reproducibility). I’ve been meaning to create a blog post about what I’ve found to be best practice here, but here’s a recent example:

> <https://github.com/JuliaPlots/PlotlyKaleido.jl/pull/27>
>
> There are three parts to this pull request, and this can easily be split apart i…f that's preferred.
> 
> \* f9ffcb0a76a3f423f4549b600ab16cf552d66f52: Creates a GitHub Action that allows you to create releases of the two javascript dependencies directly on JuliaPlots/PlotlyKaleido.jl. It's a \[manually triggered action\](https://github.com/mbauman/PlotlyKaleido.jl/actions/runs/13955687751) that allows you to set the desired version number. It downloads the given javascript resource for the given version, uploads it as \[a release artifact\](https://github.com/mbauman/PlotlyKaleido.jl/releases), and then creates \[pull request\](https://github.com/mbauman/PlotlyKaleido.jl/pull/5)(\[s\](https://github.com/mbauman/PlotlyKaleido.jl/issues/4)) to update the Artifacts.toml as needed.
> \<img src="https://github.com/user-attachments/assets/a893b8a0-3729-4bcc-9475-54bb14a70be2" width="450"\>
> 
> \* f41323d5d0e6e130e58df9fbb6878bf16e50b6cd & a308b5dedce3ec330bfada094257118d1be476fb: Are the results of merging https://github.com/mbauman/PlotlyKaleido.jl/pull/4 and https://github.com/mbauman/PlotlyKaleido.jl/pull/5 on my fork.
> \* 5b462a0b1f551787868a568e0337b7a4d5577739: is a minimally invasive patch to default to using these artifacts \*\*from my fork\*\*.
> 
> \-----------
> 
> There are two paths forward here, and I'm happy to help make either happen:
> \- merge this PR as is, and then an owner here triggers the plotly and mathjax release builds (and subsequent PRs) to move update the Artifact.toml to use those official releases.
> \- I can split this to just contain f9ffcb0a76a3f423f4549b600ab16cf552d66f52, then an owner here can trigger the actions, then merge the auto-generated PRs, then I can submit f41323d5d0e6e130e58df9fbb6878bf16e50b6cd.
> 
> Fixes #26.

GitHub promises to not mess with the bit-exact value of releases: [Update on the future stability of source code archives and hashes - The GitHub Blog](https://github.blog/open-source/git/update-on-the-future-stability-of-source-code-archives-and-hashes/)

---

<div class="post-metadata">

**Author:** ![Gregstrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregstrq/32/20620_2.png) [@Gregstrq](https://discourse.julialang.org/u/Gregstrq)\
**Post date:** [August 1, 2025, 3:06pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/5 "2025-08-01T15:06:07Z")

</div>

Yes, I had blob instead of raw.

---

<div class="post-metadata">

**Author:** ![Gregstrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregstrq/32/20620_2.png) [@Gregstrq](https://discourse.julialang.org/u/Gregstrq)\
**Post date:** [August 1, 2025, 3:22pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/6 "2025-08-01T15:22:33Z")

</div>

According to the Github blog, the usecase for releases seems to be related to `git archive` function and specifically if you depend on this archiving for security reasons.

In my case, I don’t create archive automatically and it does not have to do anything with source code. I just want to share a specific DataFrame as an Artifact using a tarball, that I generated myself (not automatically).  
Using Releases seems like an overkill for my specific usecase…

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 1, 2025, 3:51pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/7 "2025-08-01T15:51:47Z")

</div>

> [@Gregstrq](#):
>
> According to the Github blog, the usecase for releases seems to be related to `git archive` function and specifically if you depend on this archiving for security reasons.

That’s just a case where they changed the bit-exact-ness of a tarball and is what prompted the post (and promise). Release assets are a [general purpose tool](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases) to deploy pretty much _anything_ up to 2GB. Yeah, that can take work to setup, but it looks like you do already have a script to generate this tarball. You can have GitHub Actions run it for you and automatically update your Artifacts.toml. Then it’s a single click to update when your upstream data sources update.

You can of course host artifacts anywhere. This is just one mechanism that GitHub provides that I find valuable.

---

<div class="post-metadata">

**Author:** ![Gregstrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregstrq/32/20620_2.png) [@Gregstrq](https://discourse.julialang.org/u/Gregstrq)\
**Post date:** [August 1, 2025, 4:24pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/8 "2025-08-01T16:24:15Z")

</div>

I have a script that generates the file that then is being compressed into a tarball. Although, I run the script myself.  
Also, the file with generating script is one repo, and the Artifacts.toml that uses the file is in the other repo. Can I have a Github Action that triggers something in a different repository?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 1, 2025, 4:45pm UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/9 "2025-08-01T16:45:07Z")

</div>

IMV one of the biggest advantages here is that you can host the artifacts directly alongside the package itself — all in one repository. It not only feels very official, but I’ve seen that it can make some security reviews more straightforward because they then don’t need to vet a possibly-different host/platform/user/permissions/etc.

In the case of PlotlyKaleido, the GitHub action is Julia code directly in the YAML, stored directly in the package repo itself:

> <https://github.com/JuliaPlots/PlotlyKaleido.jl/pull/27/files#diff-2a86755a70d735e5d0a36f7c79a6ba7455d1c10b792db7d28156edb7a1470b82R41-R54>
>
> There are three parts to this pull request, and this can easily be split apart i…f that's preferred.
> 
> \* f9ffcb0a76a3f423f4549b600ab16cf552d66f52: Creates a GitHub Action that allows you to create releases of the two javascript dependencies directly on JuliaPlots/PlotlyKaleido.jl. It's a \[manually triggered action\](https://github.com/mbauman/PlotlyKaleido.jl/actions/runs/13955687751) that allows you to set the desired version number. It downloads the given javascript resource for the given version, uploads it as \[a release artifact\](https://github.com/mbauman/PlotlyKaleido.jl/releases), and then creates \[pull request\](https://github.com/mbauman/PlotlyKaleido.jl/pull/5)(\[s\](https://github.com/mbauman/PlotlyKaleido.jl/issues/4)) to update the Artifacts.toml as needed.
> \<img src="https://github.com/user-attachments/assets/a893b8a0-3729-4bcc-9475-54bb14a70be2" width="450"\>
> 
> \* f41323d5d0e6e130e58df9fbb6878bf16e50b6cd & a308b5dedce3ec330bfada094257118d1be476fb: Are the results of merging https://github.com/mbauman/PlotlyKaleido.jl/pull/4 and https://github.com/mbauman/PlotlyKaleido.jl/pull/5 on my fork.
> \* 5b462a0b1f551787868a568e0337b7a4d5577739: is a minimally invasive patch to default to using these artifacts \*\*from my fork\*\*.
> 
> \-----------
> 
> There are two paths forward here, and I'm happy to help make either happen:
> \- merge this PR as is, and then an owner here triggers the plotly and mathjax release builds (and subsequent PRs) to move update the Artifact.toml to use those official releases.
> \- I can split this to just contain f9ffcb0a76a3f423f4549b600ab16cf552d66f52, then an owner here can trigger the actions, then merge the auto-generated PRs, then I can submit f41323d5d0e6e130e58df9fbb6878bf16e50b6cd.
> 
> Fixes #26.

In this case, it’s proxying the upstream `.js` files without any intervening munging, but you could just as easily download the IUPAC/whatever data and then run the ETL scripts you need. By being part of the same repo, it can then open a pull request to update the Artifacts.toml file. You could also give the releases a human readable version number like `v2025.08.01`.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [August 3, 2025, 9:52am UTC](https://discourse.julialang.org/t/unstable-sha256-sum-for-artifact-hosted-in-another-github-repo/131289/10 "2025-08-03T09:52:58Z")

</div>

In fact, I believe that if you’re just fetching tarballs that aren’t releases then GitHub will sometimes regenerate them with different metadata and potentially different compression, so you cannot rely on the sha256 hash of the entire tarball being stable unless it’s a release. Matt’s suggestion seems like the way to go.
