prefix-dev / reproducible-builds

Testing reproducible builds for the conda ecosystem (using rattler-build)
https://prefix-dev.github.io/reproducible-builds/
BSD 3-Clause "New" or "Revised" License
6 stars 2 forks source link

Getting `SOURCE_DATE_EPOCH` in GitHub Actions #175

Open dhirschfeld opened 1 week ago

dhirschfeld commented 1 week ago

Just thought I'd share the snippit I use to get the SOURCE_DATE_EPOCH in GitHub Actions:

- id: source_date_epoch
  name: Get SOURCE_DATE_EPOCH
  shell: bash --noprofile --norc -euxo pipefail {0}
  run: |
    # https://github.com/moby/buildkit/blob/master/docs/build-repro.md
    if [[ ${{ github.event_name }} == "pull_request" ]]; then
      # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
      source_date_epoch=$(git for-each-ref --format="%(creatordate:format:%s)" "refs/heads/${{ github.head_ref }}")
      git show -s ${{ github.head_ref }}
    elif [[ ${{ github.event_name }} == "push" ]]; then
      # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
      source_date_epoch=$(git for-each-ref --format="%(creatordate:format:%s)" "refs/heads/${{ github.ref }}")
      git show -s ${{ github.ref }}
    elif [[ ${{ github.event_name }} == "release" ]]; then
      # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
      source_date_epoch=$(git for-each-ref --format="%(taggerdate:format:%s)" "refs/heads/${{ github.ref }}")
      git show -s ${{ github.event.release.tag_name }}
    else
      echo "::error::Unhandled event type '${{ github.event_name }}'"
      exit 1
    fi
    echo "timestamp=${source_date_epoch}" >> "${GITHUB_OUTPUT}"
    echo "isodate=$(date --iso-8601=seconds -d @${source_date_epoch})" >> "${GITHUB_OUTPUT}"

If the build is due to a commit on a PR or a push to main then the timestamp of the git commit is used. If the build was triggered by a GitHub Release being published then I use the timestamp of the (annotated) tag rather than the commit.

tdejager commented 1 week ago

That's nice! Maybe we should modify rattler-build to read the environment variable first :)

dhirschfeld commented 1 week ago

That's nice! Maybe we should modify rattler-build to read the environment variable first :)

How does rattler-build do it? If it doesn't use the date of the tag for a release it would be good to be able to override that by specifically setting the SOURCE_DATE_EPOCH env var.

dhirschfeld commented 1 week ago

For more context, normal builds are triggered by either the pull_request or push (to main) events whereas releases are triggered by the publishing of a GitHub Release (release/published event) which itself was created by the pushing of an (annotated) tag.

So, releases are always associated with an annotated tag and I use git show -s in the CI to show either the commit or the tag information.

e.g.

name: build/wheel
run-name: ${{
    format(
      '[{0}] build/wheel',
      (github.event_name == 'pull_request' && format('pr/{0}', github.event.number)) ||
      (github.event_name == 'push' && github.ref_name) ||
      (github.event_name == 'release' && github.event.release.tag_name) ||
       github.event_name
    )
  }}

on:
  # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
  push:
    branches:
      - main

  # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
  pull_request:
    branches:
      - main

  # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
  release:
    types: [published]