From cf88d628a31b0ff39daecc40f9155ddd439b7135 Mon Sep 17 00:00:00 2001 From: Matt Fishman Date: Tue, 7 May 2024 08:21:14 -0400 Subject: [PATCH] Add CI workflows and docs (#1) --- .github/dependabot.yml | 7 +++ .github/workflows/CI.yml | 79 ++++++++++++++++++++++++ .github/workflows/Register.yml | 16 +++++ .github/workflows/TagBot.yml | 31 ++++++++++ .github/workflows/format_check.yml | 35 +++++++++++ .github/workflows/format_pr.yml | 29 +++++++++ .github/workflows/format_suggestions.yml | 27 ++++++++ .gitignore | 2 +- docs/Project.toml | 2 + docs/make.jl | 16 +++++ docs/src/index.md | 14 +++++ jenkins/Dockerfile | 16 +++++ jenkins/Jenkinsfile | 61 ++++++++++++++++++ test/Project.toml | 3 +- test/runtests.jl | 46 +++++++------- 15 files changed, 361 insertions(+), 23 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/CI.yml create mode 100644 .github/workflows/Register.yml create mode 100644 .github/workflows/TagBot.yml create mode 100644 .github/workflows/format_check.yml create mode 100644 .github/workflows/format_pr.yml create mode 100644 .github/workflows/format_suggestions.yml create mode 100644 docs/Project.toml create mode 100644 docs/make.jl create mode 100644 docs/src/index.md create mode 100644 jenkins/Dockerfile create mode 100644 jenkins/Jenkinsfile diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..700707c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..1786497 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,79 @@ +name: CI +on: + push: + branches: + - main + tags: ['*'] + pull_request: + workflow_dispatch: +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} +jobs: + test: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + permissions: # needed to allow julia-actions/cache to proactively delete old caches that it has created + actions: write + contents: read + strategy: + fail-fast: false + matrix: + version: + - '1.6' + - '1.9' + os: + - ubuntu-latest + - macOS-latest + - windows-latest + arch: + - x64 + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: julia-actions/cache@v2 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v4 + with: + files: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false + docs: + name: Documentation + runs-on: ubuntu-latest + permissions: + actions: write # needed to allow julia-actions/cache to proactively delete old caches that it has created + contents: write + statuses: write + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: '1.9' + - uses: julia-actions/cache@v2 + - name: Configure doc environment + shell: julia --project=docs --color=yes {0} + run: | + using Pkg + Pkg.develop(PackageSpec(path=pwd())) + Pkg.instantiate() + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-docdeploy@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} + - name: Run doctests + shell: julia --project=docs --color=yes {0} + run: | + using Documenter: DocMeta, doctest + using ITensorGPU + DocMeta.setdocmeta!(ITensorGPU, :DocTestSetup, :(using ITensorGPU); recursive=true) + doctest(ITensorGPU) diff --git a/.github/workflows/Register.yml b/.github/workflows/Register.yml new file mode 100644 index 0000000..5b7cd3b --- /dev/null +++ b/.github/workflows/Register.yml @@ -0,0 +1,16 @@ +name: Register Package +on: + workflow_dispatch: + inputs: + version: + description: Version to register or component to bump + required: true +jobs: + register: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: julia-actions/RegisterAction@latest + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml new file mode 100644 index 0000000..0cd3114 --- /dev/null +++ b/.github/workflows/TagBot.yml @@ -0,0 +1,31 @@ +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: + inputs: + lookback: + default: "3" +permissions: + actions: read + checks: read + contents: write + deployments: read + issues: read + discussions: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: read + statuses: read +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml new file mode 100644 index 0000000..bb6d933 --- /dev/null +++ b/.github/workflows/format_check.yml @@ -0,0 +1,35 @@ +name: Format check +on: + push: + branches: [main] + tags: [v*] + pull_request: + +jobs: + format: + name: "Format Check" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: 1 + - name: Install JuliaFormatter and format + run: | + julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))' + julia -e 'using JuliaFormatter; format(".", verbose=true)' + - name: Check format + run: | + julia -e ' + out = Cmd(`git diff --name-only`) |> read |> String + if out == "" + exit(0) + else + @error "The following files have not been formatted:" + write(stdout, out) + out_diff = Cmd(`git diff`) |> read |> String + @error "Diff:" + write(stdout, out_diff) + exit(1) + @error "" + end' diff --git a/.github/workflows/format_pr.yml b/.github/workflows/format_pr.yml new file mode 100644 index 0000000..922a172 --- /dev/null +++ b/.github/workflows/format_pr.yml @@ -0,0 +1,29 @@ +name: format-pr +on: + schedule: + - cron: '0 0 * * *' +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install JuliaFormatter and format + run: | + julia -e 'import Pkg; Pkg.add("JuliaFormatter")' + julia -e 'using JuliaFormatter; format(".")' + # https://github.com/marketplace/actions/create-pull-request + # https://github.com/peter-evans/create-pull-request#reference-example + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Format .jl files + title: 'Automatic JuliaFormatter.jl run' + branch: auto-juliaformatter-pr + delete-branch: true + labels: formatting, automated pr, no changelog + - name: Check outputs + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" diff --git a/.github/workflows/format_suggestions.yml b/.github/workflows/format_suggestions.yml new file mode 100644 index 0000000..f80377a --- /dev/null +++ b/.github/workflows/format_suggestions.yml @@ -0,0 +1,27 @@ +name: Format suggestions + +on: + pull_request: + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +jobs: + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@latest + with: + version: 1 + - run: | + julia -e 'using Pkg; Pkg.add("JuliaFormatter")' + julia -e 'using JuliaFormatter; format("."; verbose=true)' + - uses: reviewdog/action-suggester@v1 + with: + tool_name: JuliaFormatter + fail_on_error: true + filter_mode: added diff --git a/.gitignore b/.gitignore index aa25970..5e65345 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,5 @@ *.jl.cov *.jl.mem .DS_Store -/Manifest.toml +Manifest.toml /dev/ diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 0000000..dfa65cd --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,2 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 0000000..95ec369 --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,16 @@ +using ITensorGPU +using Documenter + +DocMeta.setdocmeta!(ITensorGPU, :DocTestSetup, :(using ITensorGPU); recursive=true) + +makedocs(; + modules=[ITensorGPU], + authors="ITensor developers", + sitename="ITensorGPU.jl", + format=Documenter.HTML(; + canonical="https://ITensor.github.io/ITensorGPU.jl", edit_link="main", assets=String[] + ), + pages=["Home" => "index.md"], +) + +deploydocs(; repo="github.com/ITensor/ITensorGPU.jl", devbranch="main") diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..e611b69 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,14 @@ +```@meta +CurrentModule = ITensorGPU +``` + +# ITensorGPU + +Documentation for [ITensorGPU](https://github.com/ITensor/ITensorGPU.jl). + +```@index +``` + +```@autodocs +Modules = [ITensorGPU] +``` diff --git a/jenkins/Dockerfile b/jenkins/Dockerfile new file mode 100644 index 0000000..c677086 --- /dev/null +++ b/jenkins/Dockerfile @@ -0,0 +1,16 @@ +FROM nvidia/cuda:12.0.0-devel-ubuntu20.04 + +# julia +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive \ + apt-get install --yes --no-install-recommends \ + # basic stuff + curl ca-certificates \ + libcutensor-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +ARG JULIA=1.6 +RUN curl -s -L https://julialang-s3.julialang.org/bin/linux/x64/${JULIA}/julia-${JULIA}-latest-linux-x86_64.tar.gz | \ + tar -C /usr/local -x -z --strip-components=1 -f - diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile new file mode 100644 index 0000000..86c3ac6 --- /dev/null +++ b/jenkins/Jenkinsfile @@ -0,0 +1,61 @@ +pipeline { + agent none + options { + disableConcurrentBuilds() + buildDiscarder(logRotator(numToKeepStr: '8', daysToKeepStr: '20')) + } + stages { + stage('GPU Testing') { + parallel { + stage('ITensorGPU julia-1.6') { + options { + timeout(time: 45, unit: 'MINUTES') + } + agent { + dockerfile { + label 'gpu&&v100' + filename 'Dockerfile' + dir 'jenkins' + additionalBuildArgs '--build-arg JULIA=1.6' + args '--gpus "device=0"' + } + } + environment { + HOME = pwd(tmp:true) + OMP_NUM_THREADS = 4 + JULIA_NUM_THREADS = 4 + } + steps { + sh ''' + julia -e 'using Pkg; Pkg.develop(path="."); Pkg.test("ITensorGPU");' + ''' + } + } + stage('ITensorGPU julia-1.9') { + options { + timeout(time: 45, unit: 'MINUTES') + } + agent { + dockerfile { + label 'gpu&&v100' + filename 'Dockerfile' + dir 'jenkins' + additionalBuildArgs '--build-arg JULIA=1.9' + args '--gpus "device=1"' + } + } + environment { + HOME = pwd(tmp:true) + OMP_NUM_THREADS = 4 + JULIA_NUM_THREADS = 4 + } + steps { + sh ''' + julia -e 'using Pkg; Pkg.develop(path="."); Pkg.test("ITensorGPU");' + ''' + } + } + } + } + } +} diff --git a/test/Project.toml b/test/Project.toml index a3d2e41..4e383a8 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,6 +1,7 @@ [deps] -Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" +ITensorGPU = "d89171c1-af8f-46b3-badf-d2a472317c15" ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" diff --git a/test/runtests.jl b/test/runtests.jl index 71a5921..751fc3a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,27 +4,31 @@ end using ITensorGPU, Test, CUDA -println("Running ITensorGPU tests with a runtime CUDA version: $(CUDA.runtime_version())") +if !CUDA.has_cuda() + println("System does not have CUDA, skipping test.") +else + println("Running ITensorGPU tests with a runtime CUDA version: $(CUDA.runtime_version())") -CUDA.allowscalar(false) -@testset "ITensorGPU.jl" begin - #@testset "$filename" for filename in ("test_cucontract.jl",) - # println("Running $filename with autotune") - # cmd = `$(Base.julia_cmd()) -e 'using Pkg; Pkg.activate(".."); Pkg.instantiate(); include("test_cucontract.jl")'` - # run(pipeline(setenv(cmd, "CUTENSOR_AUTOTUNE" => 1); stdout=stdout, stderr=stderr)) - #end - @testset "$filename" for filename in ( - "test_dmrg.jl", - "test_cuitensor.jl", - "test_cudiag.jl", - "test_cudense.jl", - "test_cucontract.jl", - "test_cumpo.jl", - "test_cumps.jl", - "test_cutruncate.jl", - #"test_pastaq.jl", - ) - println("Running $filename") - include(filename) + CUDA.allowscalar(false) + @testset "ITensorGPU.jl" begin + #@testset "$filename" for filename in ("test_cucontract.jl",) + # println("Running $filename with autotune") + # cmd = `$(Base.julia_cmd()) -e 'using Pkg; Pkg.activate(".."); Pkg.instantiate(); include("test_cucontract.jl")'` + # run(pipeline(setenv(cmd, "CUTENSOR_AUTOTUNE" => 1); stdout=stdout, stderr=stderr)) + #end + @testset "$filename" for filename in ( + "test_dmrg.jl", + "test_cuitensor.jl", + "test_cudiag.jl", + "test_cudense.jl", + "test_cucontract.jl", + "test_cumpo.jl", + "test_cumps.jl", + "test_cutruncate.jl", + #"test_pastaq.jl", + ) + println("Running $filename") + include(filename) + end end end