| name: release |
| on: |
| workflow_run: |
| workflows: [test] |
| branches: [master] |
| types: [completed] |
| |
| defaults: |
| run: |
| shell: bash -euv -o pipefail {0} |
| |
| jobs: |
| release: |
| runs-on: ubuntu-latest |
| |
| # need to manually check for a couple things |
| # - tests passed? |
| # - we are the most recent commit on master? |
| if: ${{github.event.workflow_run.conclusion == 'success' && |
| github.event.workflow_run.head_sha == github.sha}} |
| |
| steps: |
| - uses: actions/checkout@v4 |
| with: |
| ref: ${{github.event.workflow_run.head_sha}} |
| # need workflow access since we push branches |
| # containing workflows |
| token: ${{secrets.BOT_TOKEN}} |
| # need all tags |
| fetch-depth: 0 |
| |
| # try to get results from tests |
| - uses: actions/download-artifact@v4 |
| continue-on-error: true |
| with: |
| github-token: ${{secrets.GITHUB_TOKEN}} |
| run-id: ${{github.event.workflow_run.id}} |
| pattern: '{sizes,sizes-*}' |
| merge-multiple: true |
| path: sizes |
| - uses: actions/download-artifact@v4 |
| continue-on-error: true |
| with: |
| github-token: ${{secrets.GITHUB_TOKEN}} |
| run-id: ${{github.event.workflow_run.id}} |
| pattern: '{cov,cov-*}' |
| merge-multiple: true |
| path: cov |
| - uses: actions/download-artifact@v4 |
| continue-on-error: true |
| with: |
| github-token: ${{secrets.GITHUB_TOKEN}} |
| run-id: ${{github.event.workflow_run.id}} |
| pattern: '{bench,bench-*}' |
| merge-multiple: true |
| path: bench |
| |
| - name: find-version |
| run: | |
| # rip version from lfs.h |
| LFS_VERSION="$(grep -o '^#define LFS_VERSION .*$' lfs.h \ |
| | awk '{print $3}')" |
| LFS_VERSION_MAJOR="$((0xffff & ($LFS_VERSION >> 16)))" |
| LFS_VERSION_MINOR="$((0xffff & ($LFS_VERSION >> 0)))" |
| |
| # find a new patch version based on what we find in our tags |
| LFS_VERSION_PATCH="$( \ |
| ( git describe --tags --abbrev=0 \ |
| --match="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.*" \ |
| || echo 'v0.0.-1' ) \ |
| | awk -F '.' '{print $3+1}')" |
| |
| # found new version |
| LFS_VERSION="v$LFS_VERSION_MAJOR` |
| `.$LFS_VERSION_MINOR` |
| `.$LFS_VERSION_PATCH" |
| echo "LFS_VERSION=$LFS_VERSION" |
| echo "LFS_VERSION=$LFS_VERSION" >> $GITHUB_ENV |
| echo "LFS_VERSION_MAJOR=$LFS_VERSION_MAJOR" >> $GITHUB_ENV |
| echo "LFS_VERSION_MINOR=$LFS_VERSION_MINOR" >> $GITHUB_ENV |
| echo "LFS_VERSION_PATCH=$LFS_VERSION_PATCH" >> $GITHUB_ENV |
| |
| # try to find previous version? |
| - name: find-prev-version |
| continue-on-error: true |
| run: | |
| LFS_PREV_VERSION="$( \ |
| git describe --tags --abbrev=0 --match 'v*' \ |
| || true)" |
| echo "LFS_PREV_VERSION=$LFS_PREV_VERSION" |
| echo "LFS_PREV_VERSION=$LFS_PREV_VERSION" >> $GITHUB_ENV |
| |
| # try to find results from tests |
| - name: create-table |
| run: | |
| # previous results to compare against? |
| [ -n "$LFS_PREV_VERSION" ] && curl -sS \ |
| "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/status/$LFS_PREV_VERSION` |
| `?per_page=100" \ |
| | jq -re 'select(.sha != env.GITHUB_SHA) | .statuses[]' \ |
| >> prev-status.json \ |
| || true |
| |
| # build table for GitHub |
| declare -A table |
| |
| # sizes table |
| i=0 |
| j=0 |
| for c in "" readonly threadsafe multiversion migrate error-asserts |
| do |
| # per-config results |
| c_or_default=${c:-default} |
| c_camel=${c_or_default^} |
| table[$i,$j]=$c_camel |
| ((j+=1)) |
| |
| for s in code stack structs |
| do |
| f=sizes/thumb${c:+-$c}.$s.csv |
| [ -e $f ] && table[$i,$j]=$( \ |
| export PREV="$(jq -re ' |
| select(.context == "'"sizes (thumb${c:+, $c}) / $s"'").description |
| | capture("(?<prev>[0-9∞]+)").prev' \ |
| prev-status.json || echo 0)" |
| ./scripts/summary.py $f --max=stack_limit -Y \ |
| | awk ' |
| NR==2 {$1=0; printf "%s B",$NF} |
| NR==2 && ENVIRON["PREV"]+0 != 0 { |
| printf " (%+.1f%%)",100*($NF-ENVIRON["PREV"])/ENVIRON["PREV"] |
| }' \ |
| | sed -e 's/ /\ /g') |
| ((j+=1)) |
| done |
| ((j=0, i+=1)) |
| done |
| |
| # coverage table |
| i=0 |
| j=4 |
| for s in lines branches |
| do |
| table[$i,$j]=${s^} |
| ((j+=1)) |
| |
| f=cov/cov.csv |
| [ -e $f ] && table[$i,$j]=$( \ |
| export PREV="$(jq -re ' |
| select(.context == "'"cov / $s"'").description |
| | capture("(?<prev_a>[0-9]+)/(?<prev_b>[0-9]+)") |
| | 100*((.prev_a|tonumber) / (.prev_b|tonumber))' \ |
| prev-status.json || echo 0)" |
| ./scripts/cov.py -u $f -f$s -Y \ |
| | awk -F '[ /%]+' -v s=$s ' |
| NR==2 {$1=0; printf "%d/%d %s",$2,$3,s} |
| NR==2 && ENVIRON["PREV"]+0 != 0 { |
| printf " (%+.1f%%)",$4-ENVIRON["PREV"] |
| }' \ |
| | sed -e 's/ /\ /g') |
| ((j=4, i+=1)) |
| done |
| |
| # benchmark table |
| i=3 |
| j=4 |
| for s in readed proged erased |
| do |
| table[$i,$j]=${s^} |
| ((j+=1)) |
| |
| f=bench/bench.csv |
| [ -e $f ] && table[$i,$j]=$( \ |
| export PREV="$(jq -re ' |
| select(.context == "'"bench / $s"'").description |
| | capture("(?<prev>[0-9]+)").prev' \ |
| prev-status.json || echo 0)" |
| ./scripts/summary.py $f -f$s=bench_$s -Y \ |
| | awk ' |
| NR==2 {$1=0; printf "%s B",$NF} |
| NR==2 && ENVIRON["PREV"]+0 != 0 { |
| printf " (%+.1f%%)",100*($NF-ENVIRON["PREV"])/ENVIRON["PREV"] |
| }' \ |
| | sed -e 's/ /\ /g') |
| ((j=4, i+=1)) |
| done |
| |
| # build the actual table |
| echo "| | Code | Stack | Structs | | Coverage |" >> table.txt |
| echo "|:--|-----:|------:|--------:|:--|---------:|" >> table.txt |
| for ((i=0; i<6; i++)) |
| do |
| echo -n "|" >> table.txt |
| for ((j=0; j<6; j++)) |
| do |
| echo -n " " >> table.txt |
| [[ i -eq 2 && j -eq 5 ]] && echo -n "**Benchmarks**" >> table.txt |
| echo -n "${table[$i,$j]:-}" >> table.txt |
| echo -n " |" >> table.txt |
| done |
| echo >> table.txt |
| done |
| |
| cat table.txt |
| |
| # find changes from history |
| - name: create-changes |
| run: | |
| [ -n "$LFS_PREV_VERSION" ] || exit 0 |
| # use explicit link to github commit so that release notes can |
| # be copied elsewhere |
| git log "$LFS_PREV_VERSION.." \ |
| --grep='^Merge' --invert-grep \ |
| --format="format:[\`%h\`](` |
| `https://github.com/$GITHUB_REPOSITORY/commit/%h) %s" \ |
| > changes.txt |
| echo "CHANGES:" |
| cat changes.txt |
| |
| # create and update major branches (vN and vN-prefix) |
| - name: create-major-branches |
| run: | |
| # create major branch |
| git branch "v$LFS_VERSION_MAJOR" HEAD |
| |
| # create major prefix branch |
| git config user.name ${{secrets.BOT_USER}} |
| git config user.email ${{secrets.BOT_EMAIL}} |
| git fetch "https://github.com/$GITHUB_REPOSITORY.git" \ |
| "v$LFS_VERSION_MAJOR-prefix" || true |
| ./scripts/changeprefix.py --git "lfs" "lfs$LFS_VERSION_MAJOR" |
| git branch "v$LFS_VERSION_MAJOR-prefix" $( \ |
| git commit-tree $(git write-tree) \ |
| $(git rev-parse --verify -q FETCH_HEAD | sed -e 's/^/-p /') \ |
| -p HEAD \ |
| -m "Generated v$LFS_VERSION_MAJOR prefixes") |
| git reset --hard |
| |
| # push! |
| git push --atomic origin \ |
| "v$LFS_VERSION_MAJOR" \ |
| "v$LFS_VERSION_MAJOR-prefix" |
| |
| # build release notes |
| - name: create-release |
| run: | |
| # create release and patch version tag (vN.N.N) |
| # only draft if not a patch release |
| touch release.txt |
| [ -e table.txt ] && cat table.txt >> release.txt |
| echo >> release.txt |
| [ -e changes.txt ] && cat changes.txt >> release.txt |
| cat release.txt |
| |
| curl -sS -X POST -H "authorization: token ${{secrets.BOT_TOKEN}}" \ |
| "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases" \ |
| -d "$(jq -n --rawfile release release.txt '{ |
| tag_name: env.LFS_VERSION, |
| name: env.LFS_VERSION | rtrimstr(".0"), |
| target_commitish: "${{github.event.workflow_run.head_sha}}", |
| draft: env.LFS_VERSION | endswith(".0"), |
| body: $release, |
| }' | tee /dev/stderr)" |
| |