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 34 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
133 changes: 112 additions & 21 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,131 @@ name: CI

on:
push:
branches:
- master
pull_request:
branches:
- master
# TODO: restore before merging
# branches:
# - master
# pull_request:
# branches:
# - master

env:
# TODO: restore DIST_ROOT: '/ipns/dist.ipfs.io' # content root used for calculating diff to build
DIST_ROOT: '/ipfs/QmX6J3hVtMF9Y73CKcyLHfgviEfXGFFQABWPXsD17EsBhg' # dist.ipfs.io without ipfs-update@v1.7.1
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

jobs:
build:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2-beta
- uses: actions/setup-node@v2
with:
node-version: '14'
- uses: actions/setup-go@v2
- name: Setup IPFS
run: ./scripts/ci/setup-ipfs.sh
env:
CLUSTER_USER: ${{ secrets.CLUSTER_USER }}
CLUSTER_PASSWORD: ${{ secrets.CLUSTER_PASSWORD }}
timeout-minutes: 5
- name: Build any new ./releases
run: ./dockerized make all_dists
- name: Inspect git status and contents of ./releases
run: git status && ls -Rhl ./releases
- name: Temporarily save ./releases artifacts
uses: actions/upload-artifact@v2
with:
go-version: '1.16'
- run: sudo snap install ipfs jq
- run: ipfs init --profile server
- run: ipfs daemon &
- name: Wait for ipfs daemon
run: npx wait-port http://127.0.0.1:8080/api/v0/version
- name: Connect to ipfs cluster
run: ipfs swarm connect /dnsaddr/cluster.ipfs.io
- run: make publish
# todo: add $(cat versions) to cluster (and wait)
# todo: update dist dnslink if changed.

lint:
name: releases-unsigned-diff
path: releases
retention-days: 1

lint:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2-beta
- uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm ci --no-audit --progress=false
- run: npm run lint

sign-macos:
runs-on: "macos-latest"
needs: build
steps:
- uses: actions/checkout@v2
- name: Retrieve unsigned artifacts
uses: actions/download-artifact@v2
with:
name: releases-unsigned-diff
path: releases
continue-on-error: true # skip if no releases
- name: List ./releases before
run: ls -Rhl ./releases || echo "No ./releases"
- name: Install gon via HomeBrew for code signing and app notarization
run: |
brew tap mitchellh/gon
brew install ipfs coreutils gawk gnu-sed jq mitchellh/gon/gon
ipfs init --profile test # needed for calculating NEW_CID later
- name: Import Keychain Certs
uses: apple-actions/import-codesign-certs@253ddeeac23f2bdad1646faac5c8c2832e800071 # v1@2020-02-03
with:
p12-file-base64: ${{ secrets.APPLE_CERTS_P12 }}
p12-password: ${{ secrets.APPLE_CERTS_PASS }}
- name: Verify identity used for signing
run: security find-identity -v
- name: Sign any new releases
run: ./scripts/ci/sign-new-macos-releases.sh
env:
WORK_DIR: ${{ github.workspace }}
AC_USERNAME: ${{ secrets.APPLE_AC_USERNAME }} # implicitly read from env by gon
AC_PASSWORD: ${{ secrets.APPLE_AC_PASSWORD }}
- name: List ./releases after
run: ls -Rhl ./releases || echo "No ./releases"
- name: Temporarily save notarized artifacts
uses: actions/upload-artifact@v2
with:
name: releases-signed-macos-diff
path: releases
retention-days: 1
continue-on-error: true # skip if no releases

persist:
runs-on: "ubuntu-latest"
needs: sign-macos
steps:
- uses: actions/checkout@v2
- name: Retrieve signed artifacts
uses: actions/download-artifact@v2
continue-on-error: true # skip if no releases
with:
name: releases-signed-macos-diff
path: releases
- name: List ./releases
run: ls -Rhl ./releases || echo "No ./releases"
- name: Setup IPFS
run: ./scripts/ci/setup-ipfs.sh
env:
CLUSTER_USER: ${{ secrets.CLUSTER_USER }}
CLUSTER_PASSWORD: ${{ secrets.CLUSTER_PASSWORD }}
timeout-minutes: 5
- run: ./dockerized make publish
- run: git status
- 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: "https://github.com/ipfs/distributions/commits/${{ github.sha }}"
PIN_ADD_EXTRA_ARGS: ""
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:
CONTENT_PATH: "/ipfs/${{ steps.cid-reader.outputs.CID }}/"
GIT_REVISION: ${{ github.sha }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
104 changes: 104 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Nightly

on:
push:
## Allow manual invocation
#workflow_dispatch:
#schedule:
# - cron: '0 5 * * *' # UTC
Copy link
Member

Choose a reason for hiding this comment

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

ℹ️ we will remove push and restore schedule for cron trigger + workflow_dispatch for running nightly builds on-demand


env:
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:
max-parallel: 15 # avoid using all workers from the org pool
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 }}
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
FROM ubuntu:20.04
ARG USER_UID
ARG GO_IPFS_VER
RUN apt-get update -q && apt-get install -y git curl gnupg jq build-essential gawk zip
RUN curl -s https://dist.ipfs.io/go-ipfs/v0.8.0/go-ipfs_v0.8.0_linux-amd64.tar.gz | tar vzx -C /usr/local/bin/ go-ipfs/ipfs --strip-components=1
RUN curl -s "https://dist.ipfs.io/go-ipfs/${GO_IPFS_VER}/go-ipfs_${GO_IPFS_VER}_linux-amd64.tar.gz" | tar vzx -C /usr/local/bin/ go-ipfs/ipfs --strip-components=1

RUN adduser --shell /bin/bash --home /asdf --disabled-password --gecos asdf asdf --uid $USER_UID
ENV PATH="${PATH}:/asdf/.asdf/shims:/asdf/.asdf/bin"
Expand Down
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
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ Example:
> ./dist.sh add-version fs-repo-99-to-100 v1.0.1
```

**Official build:** If you want to build official signed binaries for added version, commit changes to `dists/<dist>` and open a PR against `ipfs/distributions`.
Github Action workflow for a PR builds and signs new version using deterministic toolchain and spits out updated root CID at the end.

### Adding a new (go) distribution

Run:
Expand All @@ -107,25 +110,27 @@ The optional `sub_package` argument is used to specify a module within a repo.

### Publishing

In the root of the repository, run:
To produce a CID (`<NEW_HASH>`) that includes binaries for all versions defined in `./dists/`, in the root of the repository, run:

```sh
> make publish
```

This will build any new binaries defined by dist and the website to the `releases` dir, add it to ipfs and patch it into the existing dag for the published dist.ipfs.io. Save the hash it spits out (we'll call it `<NEW_HASH>`), that's the new hash for `dists.ipfs.io`. We also append it to a file called `versions` in the repo root (*not* checked into git).

Next, you should probably:
- This will build any new binaries defined by dist and the website to the `releases` dir, add it to ipfs and patch it into the existing dag for the published `/ipns/dist.ipfs.io`.
- Versions that are already present on the website will be reused, speeding up the build.
- Updated CID (`<NEW_HASH>`) will be printed at the end. That's the new hash for `dists.ipfs.io`. We also append it to a file called `versions` in the repo root (*not* checked into git).

1. Load the dists website in your browser to make sure everything looks right: `http://127.0.0.1:8080/ipfs/<NEW_HASH>`.
2. Compare `<NEW_HASH>` with the current `dists.ipfs.io` to make sure nothing is amiss: `ipfs object diff /ipns/dist.ipfs.io /ipfs/<NEW_HASH>`
After the local build is done, make a quick inspection:

If all looks well, **pin the hash using pinbot** (#ipfs-pinbot on Freenode, ask someone if you don't have permission to do so).
2. Load the dists website in your browser to make sure everything looks right: `http://localhost:8080/ipfs/<NEW_HASH>`.
3. Compare `<NEW_HASH>` with the current `dists.ipfs.io` to make sure nothing is amiss: `ipfs object diff /ipns/dist.ipfs.io /ipfs/<NEW_HASH>`

Finally,

1. Commit your changes and make a PR. Specifically, the changes to `dists/<dist>/versions` and `dists/<dist>/current`.
2. Make a PR with an edit on [protocol/infra](https://github.com/protocol/infra/blob/master/dns/config/dist.ipfs.io.yaml) with the hash you got from `make publish` and a link to the PR above.
2. Wait for [Github Action](https://github.com/ipfs/distributions/actions/) on your PR to build **signed** binaries. `<NEW_SIGNED_HASH>` will be different than one from local build.
3. Make a PR with an edit on [protocol/infra](https://github.com/protocol/infra/blob/master/dns/config/dist.ipfs.io.yaml) with `<NEW_SIGNED_HASH>` you got from the Github Action output and a link to the PR above.
- TODO: this step may be automated in the future - see the [discussion](https://github.com/ipfs/distributions/issues/372).

If you have permission, you can just merge the PR, update the DNS, and then immediately, close the issue on ipfs/infrastructure. Ping someone on IRC.

Expand Down
Loading