diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 449ad95..2208e94 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -18,36 +18,42 @@ jobs: with: version: '1.10' - # - name: Last release tag + Run main script + Git tree hash + Next release tag - # run: | - # export LAST_QUBOLIB_TAG="$(gh release view | sed -nr 's/tag:\s*(v\S*)/\1/p')" - # julia "$GITHUB_WORKSPACE/deployment/script.jl" - # export GIT_TREE_HASH=$(cat $GITHUB_WORKSPACE/deployment/tree.hash) - # echo "GIT_TREE_HASH=$GIT_TREE_HASH" >> $GITHUB_ENV - # export NEXT_QUBOLIB_TAG=$(cat $GITHUB_WORKSPACE/deployment/next.tag) - # echo "TAG=$NEXT_QUBOLIB_TAG" >> $GITHUB_ENV - - # - name: Compute SHA256 for the compressed tarball - # run: | - # SHA_256="$(sha256sum -z $GITHUB_WORKSPACE/dist/qubolib.tar.gz | cut -d " " -f 1)" - # echo "SHA_256=$SHA_256" >> $GITHUB_ENV + - name: Create distribution directories + run: | + cd $GITHUB_WORKSPACE + mkpath ./dist/build/ + mkpath ./dist/cache/ - # - name: Write release title - # run: | - # TITLE="QUBOLib $TAG" - # echo "TITLE=$TITLE" >> $GITHUB_ENV + - name: Retrieve Last Release Tag + run: | + cd $GITHUB_WORKSPACE + LAST_TAG="$(gh release view | sed -nr 's/tag:\s*(v\S*)/\1/p')" + echo "$LAST_TAG" >> ./dist/build/last.tag + + - name: Build and Deploy QUBOLib + run: | + cd $GITHUB_WORKSPACE + julia --proj=./scripts/build ./scripts/build/script.jl --deploy - # - name: Write release notes - # run: envsubst < "$GITHUB_WORKSPACE/deployment/NOTES.md" > "$RUNNER_TEMP/NOTES.md" + - name: Load Next Release Tag + run: | + cd $GITHUB_WORKSPACE + NEXT_TAG="$(cat $GITHUB_WORKSPACE/dist/build/next.tag)" + echo "NEXT_TAG=$NEXT_TAG" >> $GITHUB_ENV - # - name: Publish release - # run: > - # gh release create $TAG - # --latest - # --notes-file "$RUNNER_TEMP/NOTES.md" - # --title "$TITLE" - # --target $GITHUB_SHA - # dist/qubolib.tar.gz + - name: Write release title + run: | + TITLE="$(cat $GITHUB_WORKSPACE/dist/build/title.txt)" + echo "TITLE=$TITLE" >> $GITHUB_ENV + + - name: Publish QUBOLib data release + run: > + gh release create $NEXT_TAG + --latest + --notes-file "$GITHUB_WORKSPACE/dist/build/NOTES.md" + --title "$TITLE" + --target $GITHUB_SHA + $GITHUB_WORKSPACE/dist/build/qubolib.tar.gz # - name: Update Documentation # run: | @@ -55,4 +61,21 @@ jobs: # git config user.email "github-actions@github.com" # git add "./*README.md" # git commit --allow-empty -m "Update Documentation" - # git push \ No newline at end of file + # git push + + - name: Clean up old mirror release + run: | + gh release delete mirror --yes || true + git push origin --delete refs/tags/mirror || true + + - name: Switch to mirror branch + run: git checkout mirror + + - name: Publish mirror release + run: > + gh release create mirror + --prerelease + --notes-file "$GITHUB_WORKSPACE/dist/build/mirror/NOTES.md" + --title "$SUBJECT" + --target $GITHUB_SHA + $GITHUB_WORKSPACE/dist/build/mirror/*.zip \ No newline at end of file diff --git a/scripts/build/build.jl b/scripts/build/build.jl index 378ea7c..19e00bf 100644 --- a/scripts/build/build.jl +++ b/scripts/build/build.jl @@ -1,31 +1,35 @@ -using JuliaFormatter -using LaTeXStrings +import Pkg +import Tar import Downloads import QUBOLib import QUBOTools +using JuliaFormatter +using LaTeXStrings + include("library/clear.jl") include("library/deploy.jl") include("sources/hen.jl") include("sources/qplib.jl") -function build_standard_qubolib( - path::AbstractString; +function build_qubolib!( + path::AbstractString = pwd(); + deploy::Bool = false, clear_cache::Bool = false, clear_build::Bool = false, ) - @info "Building QUBOLib v$(QUBOLib.__version__()) @ $(path)" + @info "Building QUBOLib v$(QUBOLib.__version__()) @ '$path'" if clear_cache - @info "[Clearing Cache]" + @info "[QUBOLib] Clear Cache" clear_cache!(path) end if clear_build - @info "[Clearing Build]" + @info "[QUBOLib] Clear Build" QUBOLib.access(; path, clear = true) |> close end @@ -38,14 +42,27 @@ function build_standard_qubolib( build_qplib!(index) end + @info "[QUBOLib] Build done!" + + if deploy + @info "[QUBOLib] Deploy Library" + + QUBOLib.access(; path) do index + deploy_qubolib!(index) + deploy_hen!(index) + deploy_qplib!(index) + end + end + return nothing end function main(args::Vector{String} = ARGS) QUBOLib.print_logo(stdout) - build_standard_qubolib( - QUBOLib.root_path(); + build_qubolib!( + pwd(); + deploy = ("--deploy" ∈ args), clear_cache = ("--clear-cache" ∈ args), clear_build = ("--clear-build" ∈ args), ) diff --git a/scripts/build/library/deploy.jl b/scripts/build/library/deploy.jl index 8d157af..7304abd 100644 --- a/scripts/build/library/deploy.jl +++ b/scripts/build/library/deploy.jl @@ -1,92 +1,175 @@ -function deploy!(path::AbstractString) +function deploy_qubolib!(index::QUBOLib.LibraryIndex) @assert Sys.islinux() + close(index) + # Calculate tree hash - git_tree_hash = bytes2hex(Pkg.GitTools.tree_hash(QUBOLib.library_path(path))) + @info "[QUBOLib] Compute Tree Hash" + + git_tree_hash = bytes2hex(Pkg.GitTools.tree_hash(QUBOLib.library_path(index))) + + write(joinpath(QUBOLib.build_path(index), "git-tree.hash"), git_tree_hash) # Build tarball - temp_path = abspath(Tar.create(QUBOLib.library_path(path))) + @info "[QUBOLib] Build Tar ball" + + temp_path = abspath(Tar.create(QUBOLib.library_path(index))) # Compress tarball run(`gzip -9 $temp_path`) # Move tarball - tar_ball_path = mkpath(abspath(QUBOLib.dist_path(path), "qubolib.tar.gz")) + @info "[QUBOLib] Move Tar ball" + + tar_ball_path = joinpath(QUBOLib.build_path(index), "qubolib.tar.gz") rm(tar_ball_path; force = true) + mkpath(dirname(tar_ball_path)) + cp("$temp_path.gz", tar_ball_path; force = true) # Remove temporary files + @info "[QUBOLib] Clear Temporary files" + rm(temp_path; force = true) rm("$temp_path.gz"; force = true) - # Write hash to file - write(joinpath(QUBOLib.build_path(path), "git-tree.hash"), git_tree_hash) - # Also, compute sha256 sum - tar_ball_hash = read(pipeline(`sha256sum -z $tar_ball_path`, `cut -d ' ' -f 1`), String) + @info "[QUBOLib] Compute SHA256 hash sum" + + tar_ball_hash = strip(read(pipeline(`sha256sum -z $tar_ball_path`, `cut -d ' ' -f 1`), String)) - write(joinpath(QUBOLib.build_path(path), "tar-ball.hash"), tar_ball_hash) + write(joinpath(QUBOLib.build_path(index), "tar-ball.hash"), tar_ball_hash) # Retrieve last QUBOLib tag - last_tag = read(joinpath(QUBOLib.build_path(path), "last.tag"), String) + @info "[QUBOLib] Generate release tag" + + last_tag = last_data_tag(index) next_tag = next_data_tag(last_tag) - write(joinpath(QUBOLib.build_path(path), "next.tag"), next_tag) + write(joinpath(QUBOLib.build_path(index), "next.tag"), next_tag) # Write Artifacts.toml entry + @info "[QUBOLib] Generate Artifacts.toml" + artifact_entry = """ [qubolib] git-tree-sha1 = "$(git_tree_hash)" lazy = true [[qubolib.download]] - url = "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/$(qubolib_tag)/qubolib.tar.gz" + url = "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/$(next_tag)/qubolib.tar.gz" sha256 = "$(tar_ball_hash)" """ - write(joinpath(QUBOLib.build_path(path), "Artifacts.toml"), artifact_entry) + write(joinpath(QUBOLib.build_path(index), "Artifacts.toml"), artifact_entry) + + # Write release information + @info "[QUBOLib] Generate release title" + + release_title = "QUBOLib Library Data $(next_tag)" + + write(joinpath(QUBOLib.build_path(index), "title.txt"), release_title) + + @info "[QUBOLib] Generate release notes" + + release_notes = """ + # $(release_title) Release Notes + + ## `Artifact.toml` + + To be able to access the `qubolib` artifact in your project, add the following entry to `Artifacts.toml`. + + ```toml + $(artifact_entry) + ``` + """ + + write(joinpath(QUBOLib.build_path(index), "NOTES.md"), release_notes) + + @info "[QUBOLib] Generate Mirror release notes" + + mirror_notes = """ + # QUBOLib Data Mirror Release Notes + + This release provides access to mirrored and preprocessed instances from other libraries. + """ + + write(joinpath(QUBOLib.build_path(index), "mirror", "NOTES.md"), mirror_notes) + + @info "[QUBOLib] Deployment done!" return nothing end -function next_data_tag(last_tag::AbstractString)::String - return next_data_tag(parse(VersionNumber, last_tag)) -end +function last_data_tag(index::QUBOLib.LibraryIndex)::Union{String,Nothing} + last_tag_path = joinpath(QUBOLib.build_path(index), "last.tag") -function next_data_tag(last_tag::VersionNumber)::String - next_tag = if isempty(last_tag.prerelease) - @assert isempty(last_tag.build) + if isdir(last_tag_path) + return strip(read(last_tag_path, String)) + else + @warn """ + No last tag information found @ '$last_tag_path'. + Thus, release tag must be created manually and 'Artifact.toml' has to be updated accordingly. + """ + + return nothing + end +end +function next_data_tag(::Nothing)::String + next_tag = let version = QUBOLib.__version__() VersionNumber( - last_tag.major, - last_tag.minor, - last_tag.patch, + version.major, + version.minor, + version.patch, ("data",), - (1,), + (1,) ) - else # !isempty(last_tag.prerelease) - @assert only(last_tag.prerelease) == "data" + end - if isempty(last_tag.build) - VersionNumber( - last_tag.major, - last_tag.minor, - last_tag.patch, - last_tag.prerelease, - (1,), - ) - else - @assert only(last_tag.build) isa Integer "last_tag.build = $(last_tag.build)" + return "v$(next_tag)" +end + +function next_data_tag(last_tag::AbstractString)::String + return next_data_tag(parse(VersionNumber, last_tag)) +end + +function next_data_tag(last_tag::VersionNumber)::String + next_tag = let version = QUBOLib.__version__() + if isempty(last_tag.prerelease) + @assert isempty(last_tag.build) VersionNumber( - last_tag.major, - last_tag.minor, - last_tag.patch, - last_tag.prerelease, - (only(last_tag.build) + 1,) + version.major, + version.minor, + version.patch, + ("data",), + (1,), ) + else # !isempty(last_tag.prerelease) + @assert only(last_tag.prerelease) == "data" + + if isempty(last_tag.build) + VersionNumber( + version.major, + version.minor, + version.patch, + ("data",), + (1,), + ) + else + @assert only(last_tag.build) isa Integer "last_tag.build = $(last_tag.build)" + + VersionNumber( + version.major, + version.minor, + version.patch, + ("data",), + (only(last_tag.build) + 1,) + ) + end end end diff --git a/scripts/build/sources/hen.jl b/scripts/build/sources/hen.jl index e900dd3..8bbb31c 100644 --- a/scripts/build/sources/hen.jl +++ b/scripts/build/sources/hen.jl @@ -1,6 +1,6 @@ const HEN_DATA = Dict( "arXiv-1903-10928-3r3x" => Dict( - :url => "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/mirror-v0/arXiv-1903-10928-3r3x.zip", + :url => "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/mirror/arXiv-1903-10928-3r3x.zip", :data => Dict{String,Any}( "name" => "3-Regular 3-XORSAT (arXiv:1903.10928)", "author" => ["Itay Hen"], @@ -10,7 +10,7 @@ const HEN_DATA = Dict( ), ), "arXiv-1903-10928-5r5x" => Dict( - :url => "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/mirror-v0/arXiv-1903-10928-5r5x.zip", + :url => "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/mirror/arXiv-1903-10928-5r5x.zip", :data => Dict{String,Any}( "name" => "5-Regular 5-XORSAT (arXiv:1903.10928)", "author" => ["Itay Hen"], @@ -20,7 +20,7 @@ const HEN_DATA = Dict( ), ), "arXiv-2103-08464-3r3x" => Dict( - :url => "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/mirror-v0/arXiv-2103-08464-3r3x.zip", + :url => "https://github.com/JuliaQUBO/QUBOLib.jl/releases/download/mirror/arXiv-2103-08464-3r3x.zip", :data => Dict{String,Any}( "name" => "3-Regular 3-XORSAT (arXiv:2103.08464)", "author" => ["Matthew Kowalsky", "Tameem Albash", "Itay Hen", "Daniel A. Lidar"], @@ -67,8 +67,6 @@ function build_hen!(index::QUBOLib.LibraryIndex; cache::Bool = true) end function build_hen!(index::QUBOLib.LibraryIndex, code::AbstractString; cache::Bool = true) - @info "[$code] Building index" - if QUBOLib.has_collection(index, code) @info "[$code] Collection already exists" @@ -81,6 +79,8 @@ function build_hen!(index::QUBOLib.LibraryIndex, code::AbstractString; cache::Bo load_hen!(index, code) + @info "[$code] Building index" + QUBOLib.add_collection!(index, code, HEN_DATA[code][:data]) data_path = QUBOLib.cache_data_path(index, code) @@ -130,3 +130,17 @@ function patch_hen!(index::QUBOLib.LibraryIndex, code::AbstractString) return nothing end + +function deploy_hen!(index::QUBOLib.LibraryIndex) + close(index) + + for code in keys(HEN_DATA) + src_path = QUBOLib.cache_data_path(index, code) + dst_path = mkpath(joinpath(QUBOLib.build_path(index), "mirror")) + zip_path = joinpath(dst_path, "$code.zip") + + run(`zip -q -j -r $zip_path $src_path`) + end + + return nothing +end diff --git a/scripts/build/sources/qplib.jl b/scripts/build/sources/qplib.jl index 6891460..c909a38 100644 --- a/scripts/build/sources/qplib.jl +++ b/scripts/build/sources/qplib.jl @@ -301,8 +301,6 @@ function build_qplib!(index::QUBOLib.LibraryIndex; cache::Bool = true) end end - @info "[qplib] Done!" - return nothing end @@ -354,3 +352,15 @@ function load_qplib!(index::QUBOLib.LibraryIndex) return code_list end + +function deploy_qplib!(index::QUBOLib.LibraryIndex) + close(index) + + src_path = QUBOLib.cache_data_path(index, "qplib") + dst_path = mkpath(joinpath(QUBOLib.build_path(index), "mirror")) + zip_path = joinpath(dst_path, "qplib.zip") + + run(`zip -q -j -r $zip_path $src_path`) + + return nothing +end diff --git a/src/QUBOLib.jl b/src/QUBOLib.jl index 8542f4e..e32008b 100644 --- a/src/QUBOLib.jl +++ b/src/QUBOLib.jl @@ -30,12 +30,12 @@ const QUBOLIB_LOGO = raw""" ┃ ██ ▀▀▄███ ██ ██ ██ ██ ██ ██ ┃ ┃ ▀██████▀▄▄ ▀██████▀ █████▀ ▀██████▀ ┃ ┃ ┃ -┃ ██ ██ ██ ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ ┃ -┃ ██ ██ ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ ┃ -┃ ██ ██ █████▄ ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ ┃ -┃ ██ ██ ██ ██ ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ ┃ -┃ ███████ ██ █████▀ ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ ┃ -┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ +┃ ██ ██ ██ ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ ┃ Pedro Maciel Xavier¹² +┃ ██ ██ ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ ┃ David E. Bernal Neira² +┃ ██ ██ █████▄ ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ ┃ +┃ ██ ██ ██ ██ ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ ┃ ¹Universidade Federal do Rio de Janeiro © 2024 +┃ ███████ ██ █████▀ ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ ┃ ²Purdue University © 2024 +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ """ function print_logo(io::IO = stdout) diff --git a/src/actions/build.jl b/src/actions/build.jl deleted file mode 100644 index e69de29..0000000