Skip to content
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

feat: create nightly builds #369

Merged
merged 36 commits into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cd78bdf
wip: signing poc with hardcoded dist details
lidel Jul 12, 2021
230d1cd
feat: create nightly builds
iand Jul 21, 2021
1bb2f20
Ensure nightly dates use utc
iand Jul 22, 2021
7208eae
Allow manual invocation of nightly workflow
iand Jul 22, 2021
42531b6
Keep last 7 nightly versions in published versions file
iand Jul 23, 2021
18ca56e
Touch existing versions file to create it
iand Jul 23, 2021
4870454
Create output dir earlier
iand Jul 23, 2021
8e11abe
wip: debugging pinning to cluster
lidel Jul 22, 2021
2cb0822
Publish after nightly build
iand Jul 26, 2021
f3c456d
wip: wait for 2 cluster confirmations
lidel Jul 26, 2021
3e9a8e2
wip: speed up build
lidel Jul 26, 2021
796aaae
wip: PR preview link
lidel Jul 26, 2021
ed656e5
wip: no-op build
lidel Jul 26, 2021
7d222b5
refactor: use GO_IPFS_VER in dockerized build
lidel Jul 27, 2021
f115f93
docs: DNSLink discussion
lidel Jul 27, 2021
9acff7e
refactor: simplify
lidel Jul 27, 2021
5ea24dc
refactor: avoid polluting ./releases
lidel Jul 27, 2021
5df807b
refactor: respect nightly cut-off date
lidel Jul 27, 2021
716ebaf
wip: see how long all nightlies take to build and pin
lidel Jul 27, 2021
6e513af
fix: dockerized build on ci
lidel Jul 27, 2021
baa201f
fix: vtag dists like fs-repo-migrations/fs-repo-*
lidel Jul 28, 2021
a2e8f26
wip: run each dist in matrix
lidel Jul 28, 2021
87c0b11
refactor: scripts/ci/setup-ipfs.sh
lidel Jul 28, 2021
9544654
refactor: scripts/ci/pin-to-cluster.sh
lidel Jul 28, 2021
c239cfb
fix: quic perf
lidel Jul 28, 2021
ef7843a
refactor: sign-new-macos-releases.sh
lidel Jul 28, 2021
835df84
refactor: github-preview-link.sh
lidel Jul 28, 2021
1c9b839
test: signed release built for ipfs-update@v1.7.1
lidel Jul 28, 2021
00dc19b
Merge branch 'feat/signed-ci-build' into feat/issue-363-nightlies
lidel Jul 28, 2021
e2570b8
refactor: reuse ./scripts/ci
lidel Jul 28, 2021
947f37d
fix: nightly cleanup
lidel Jul 28, 2021
5277083
refactor: deduplicate pinning
lidel Jul 28, 2021
843feda
feat: fill issue for every broken nightly build
lidel Jul 28, 2021
08caa11
fix: github status link
lidel Jul 29, 2021
dc8b64e
Merge branch 'master' into feat/issue-363-nightlies
lidel Aug 3, 2021
6a29155
chore: restore target trigger (cron and manual)
lidel Aug 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Nightly

on:
workflow_dispatch:
inputs:
dist_root:
description: 'DIST_ROOT'
required: true
default: '/ipns/dist.ipfs.io'
schedule:
- cron: '0 5 * * *' # UTC

env:
DIST_ROOT: ${{ github.event.inputs.custom_dist_root || '/ipns/dist.ipfs.io' }} # content root used for calculating diff to build
GO_IPFS_VER: 'v0.9.1' # go-ipfs daemon used for chunking and applying diff
CLUSTER_CTL_VER: 'v0.14.0' # ipfs-cluster-ctl used for pinning

concurrency:
group: nightly
cancel-in-progress: true

jobs:
prepare-matrix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- id: set-matrix
run: echo "::set-output name=matrix::$(jq -nc '$ARGS.positional' --args $(ls ./dists -1))"
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}

build:
runs-on: "ubuntu-latest"
needs: prepare-matrix
strategy:
fail-fast: false
matrix:
dist_name: ${{ fromJson(needs.prepare-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v2
- name: Setup IPFS
run: ./scripts/ci/setup-ipfs.sh
env:
CLUSTER_USER: ${{ secrets.CLUSTER_USER }}
CLUSTER_PASSWORD: ${{ secrets.CLUSTER_PASSWORD }}
timeout-minutes: 5
- run: cd ./dists/${{ matrix.dist_name }} && make nightly
- run: ./dockerized make publish
- name: Create issue if build failed
uses: actions/github-script@v4
Copy link
Member

Choose a reason for hiding this comment

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

ℹ️ Third-party turn-key solutions exists, but I decided to give actions/github-script a try. It is an official action provided by GitHub, provides JS porcelain for running arbitrary API calls.

Debugging is a bit painful, but being written in JS could make it more dev friendly than bash+curl, allowing more people to maintain/extend. actions/github-script is extremely powerful, only caveat is that it needs a personal access token to do anything outside the current repo.

We may leverage it even more for developer flow automation tailored to our needs. For example, it could automatically create/label issues and add them to specific column in specific project.

if: ${{ failure() }}
with:
script: |
const title = 'Nightly build failed for ${{ matrix.dist_name }}'
const body = '${{ matrix.dist_name }} failed to build from the latest commit: https://github.com/ipfs/distributions/actions/runs/${{ github.run_id }}'
const opts = { owner: context.repo.owner, repo: context.repo.repo }
const response = await github.search.issuesAndPullRequests({
q: `repo:ipfs/distributions is:issue is:open in:title ${title}`
})
console.log('github.issuesAndPullRequests', response)
let link
if (response.data.items.length === 0) {
const created = await github.issues.create({ ...opts, title, body,
labels: ['kind/bug', 'need/triage']
})
console.log('no open issues, created a new one', created)
link = created.data.html_url
}
for (const issue of response.data.items) {
if (issue.title !== title) continue
console.log('found existing open issue', issue)
const created = await github.issues.createComment({ ...opts,
issue_number: issue.number,
body
})
console.log('commented on existing open issue', created)
link = created.data.html_url
}
await github.repos.createCommitStatus({ ...opts,
sha: '${{ github.sha }}',
state: 'error',
target_url: link,
context: 'Problem with ${{ matrix.dist_name }}',
description: 'See details in the linked issue'
})
- name: Inspect git status and contents of ./releases
run: git status && ls -Rhl ./releases
- name: Read CID of updated DAG
id: cid-reader
run: echo "::set-output name=CID::$(tail -1 ./versions)"
- name: Pin new website to ipfs-websites.collab.ipfscluster.io
run: ./scripts/ci/pin-to-cluster.sh
env:
PIN_CID: ${{ steps.cid-reader.outputs.CID }}
PIN_NAME: "ipfs/distributions/nightly/${{ matrix.dist_name }}"
PIN_ADD_EXTRA_ARGS: "--expire-in 168h"
Copy link
Member

Choose a reason for hiding this comment

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

ℹ️ this pins nightly artifacts only for a week

CLUSTER_USER: ${{ secrets.CLUSTER_USER }}
CLUSTER_PASSWORD: ${{ secrets.CLUSTER_PASSWORD }}
timeout-minutes: 60
- name: Update PR status with preview link
run: ./scripts/ci/github-preview-link.sh
env:
GITHUB_TITLE: "Preview for ${{ matrix.dist_name }}"
CONTENT_PATH: "/ipfs/${{ steps.cid-reader.outputs.CID }}/${{ matrix.dist_name }}"
GIT_REVISION: ${{ github.sha }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 changes: 15 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
all: deps releases all_dists site

.PHONY: all all_dists deps
all_dists: $(notdir $(wildcard dists/*))
DISTS = $(notdir $(wildcard dists/*))

%:
NDISTS = $(DISTS:%=nightly-%)

.PHONY: all all_dists deps nightly
all_dists: $(DISTS)

$(DISTS):
@echo "** $@ **"
$(MAKE) -C dists/$@
@echo ""

nightly: $(NDISTS)

$(NDISTS):
@echo "** $@ Nightly **"
$(MAKE) -C dists/$(@:nightly-%=%) nightly
@echo ""

deps:
./deps-check.sh

releases:
mkdir -p releases


.PHONY: site
site: deps
@echo "** Building site **"
Expand Down
78 changes: 62 additions & 16 deletions build-go.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ function printInitialDistfile() {
"name": "$distname",
"owner": "$(< repo-owner)",
"description": "$(< description)",
"date": "$(date '+%B %d, %Y')",
"date": "$(date -u '+%B %d, %Y')",
"platforms": {}
}
EOF
Expand All @@ -211,15 +211,15 @@ function printBuildInfo() {
go version
echo "git sha of code: $commit"
uname -a
echo "built on $(date)"
echo "built on $(date -u)"
}

function buildWithMatrix() {
local matfile=$1
local package=$2
local output=$3
local commit=$4
local version=$5
local buildVersion=$5

test -n "$output" || fail "error: output dir not specified"
test -e "$matfile" || fail "build matrix $matfile does not exist"
Expand All @@ -229,13 +229,13 @@ function buildWithMatrix() {
local distname
distname=$(basename "$(pwd)")

printInitialDistfile "$distname" "$version" > dist.json
printInitialDistfile "$distname" "$buildVersion" > dist.json
printBuildInfo "$commit" > "$output/build-info"

# build each os/arch combo
while read -r goos goarch
do
doBuild "$goos" "$goarch" "$package" "$output" "$version"
doBuild "$goos" "$goarch" "$package" "$output" "$buildVersion"
done < "$matfile"

# build the source
Expand All @@ -251,19 +251,42 @@ function cleanRepo() {
git -C "$repopath" reset --hard
}

function nightlyRevision() {
local repopath=$1
local version=$2

# Use default branch, may be master, main or some other name
default_branch="$(git -C "$repopath" symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')"
# Find the last commit before nightly cut-off
cutoff_date="${version#nightly-}"
git -C "$repopath" rev-list -1 --first-parent --before="$cutoff_date" "$default_branch"
}

function checkoutVersion() {
local repopath=$1
local ref=$2
local version=$2

test -n "$repopath" || fail "checkoutVersion: no repo to check out specified"

echo "==> checking out version $ref in $repopath"
cleanRepo "$repopath"
case $version in
nightly*)
ref="$(nightlyRevision "$repopath" "$version")"
;;
*)
ref=$version

# If there is a vtag, then checkout using <vtag>/<version>
# ('vtag' file is used for indicating 'submodule'
# such as 'fs-repo-migrations/fs-repo-0-to-1',
# those have release tags like 'fs-repo-0-to-1/v1.0.0')
if [ -e vtag ]; then
ref="$(cat vtag)/${version}"
fi
;;
esac

# If there is a vtag, then checkout using <vtag>/<version>
if [ -e vtag ]; then
ref="$(cat vtag)/${ref}"
fi
echo "==> checking out version $version (git: $ref) in $repopath"
cleanRepo "$repopath"

git -C "$repopath" checkout "$ref" > /dev/null || fail "failed to check out $ref in $reporoot"
}
Expand Down Expand Up @@ -338,7 +361,11 @@ function startGoBuilds() {
fi

echo "comparing $versions with $existing/$distname/versions"
newVersions=$(comm --nocheck-order -13 <(ipfs cat "$existing/$distname/versions") "$versions")

existingVersions=$(mktemp)
ipfs cat "$existing/$distname/versions" > "$existingVersions"

newVersions=$(comm --nocheck-order -13 "$existingVersions" "$versions")

if [ -z "$newVersions" ]; then
notice "skipping $distname - all versions published at $existing"
Expand Down Expand Up @@ -369,11 +396,22 @@ function startGoBuilds() {

while read -r version
do
if [ -e "$outputDir/$version" ]; then
outputVersion=$outputDir/$version

if [ -e "$outputVersion" ]; then
echo "$version already exists, skipping..."
continue
fi

case $version in
nightly*)
buildVersion="$version-$(nightlyRevision "$repopath" "$version" | head -c 7)"
;;
*)
buildVersion=$version
;;
esac

notice "building version $version binaries"
checkoutVersion "$repopath" "$version"
installDeps "$repopath" > "deps-$version.log" 2>&1
Expand All @@ -394,13 +432,21 @@ function startGoBuilds() {
go mod edit -require "$repo@$(git -C "$repopath" rev-parse HEAD)"
fi

buildWithMatrix "$matfile" "$repo/$package" "$outputDir/$version" "$(currentSha "$repopath")" "$version"
buildWithMatrix "$matfile" "$repo/$package" "$outputVersion" "$(currentSha "$repopath")" "$buildVersion"
echo ""
done <<< "$newVersions"

cp "$versions" "$outputDir/versions"
# Additional cleanup/normalization for nightly builds
if grep -h ^nightly "$versions" "$existingVersions" > /dev/null; then
# Keep all tagged versions from repo
grep -v ^nightly "$versions" > "$outputDir/versions"
# Keep at most 7 nightly versions
grep -h ^nightly "$versions" "$existingVersions" | sort -ur | head -n7 >> "$outputDir/versions"
fi

notice "build complete!"
}

startGoBuilds "$1" "$2" "$3" "$4" "$5"

# vim: noet
10 changes: 9 additions & 1 deletion common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,23 @@ relpath = $(dir $(lastword $(MAKEFILE_LIST)))
# Default values
distname ?= $(notdir ${CURDIR})
releases ?= $(relpath)releases/${distname}
versions ?= versions

nightlyVer = nightly-$(shell date -u '+%Y-%m-%d')


all: dist

dist:
${relpath}build-go.sh "${distname}" "${repo}" "${package}" versions
${relpath}build-go.sh "${distname}" "${repo}" "${package}" "${versions}"

update_sources:
cd gopath/src/${repo}
git fetch

clean:
rm -rf $(releases)

nightly:
grep -qxF ${nightlyVer} versions || echo ${nightlyVer} >> versions

1 change: 1 addition & 0 deletions dist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ case $1 in

case "$nvers" in
*-*) echo "WARNING: not marking pre-release $dist $nvers as the current version." ;;
nightly) nvers=$nvers-$(date -u '+%Y-%m-%d') ;;
*) echo "$nvers" > "dists/$dist/current" ;;
esac

Expand Down
6 changes: 3 additions & 3 deletions scripts/ci/github-preview-link.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/usr/bin/env bash
set -e

PREVIEW_URL="https://dweb.link$CONTENT_PATH"
PREVIEW_URL=${PREVIEW_URL:-"https://dweb.link$CONTENT_PATH"}
API_PARAMS=$(jq --monochrome-output --null-input \
--arg state "success" \
--arg target_url "$PREVIEW_URL" \
--arg description "Preview updated website on IPFS" \
--arg context "Preview is ready" \
--arg description "${GITHUB_DESCRIPTION:-"Preview updated website on IPFS"}" \
--arg context "${GITHUB_TITLE:-"Preview is ready"}" \
'{ state: $state, target_url: $target_url, description: $description, context: $context }' )
curl --output /dev/null --silent --show-error \
-X POST -H "Authorization: Bearer $GITHUB_TOKEN" -H 'Content-Type: application/json' \
Expand Down