From 801d307807c98a35acd6f34bb44ed6825376baef Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Sat, 17 Dec 2022 20:40:56 -0800 Subject: [PATCH 01/39] trace elk edges to shape border --- d2layouts/d2elklayout/layout.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/d2layouts/d2elklayout/layout.go b/d2layouts/d2elklayout/layout.go index 63b26c95f..dce31bc8a 100644 --- a/d2layouts/d2elklayout/layout.go +++ b/d2layouts/d2elklayout/layout.go @@ -10,6 +10,7 @@ import ( "encoding/json" "fmt" "math" + "strings" "github.com/dop251/goja" @@ -21,6 +22,7 @@ import ( "oss.terrastruct.com/d2/d2target" "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/label" + "oss.terrastruct.com/d2/lib/shape" ) //go:embed elk.js @@ -289,6 +291,14 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) { }) } + startIndex, endIndex := 0, len(points)-1 + srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Attributes.Shape.Value)], edge.Src.Box) + dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Attributes.Shape.Value)], edge.Dst.Box) + + // trace the edge to the specific shape's border + points[startIndex] = shape.TraceToShapeBorder(srcShape, points[startIndex], points[startIndex+1]) + points[endIndex] = shape.TraceToShapeBorder(dstShape, points[endIndex], points[endIndex-1]) + if edge.Attributes.Label.Value != "" { edge.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } From 98a2d59aea3838d857432209ca4dae42c3722cb4 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Sat, 17 Dec 2022 20:41:42 -0800 Subject: [PATCH 02/39] update tests --- .../stable/all_shapes/elk/board.exp.json | 26 +++++----- .../stable/all_shapes/elk/sketch.exp.svg | 2 +- .../all_shapes_multiple/elk/board.exp.json | 26 +++++----- .../all_shapes_multiple/elk/sketch.exp.svg | 2 +- .../all_shapes_shadow/elk/board.exp.json | 26 +++++----- .../all_shapes_shadow/elk/sketch.exp.svg | 2 +- .../arrowhead_adjustment/elk/board.exp.json | 18 +++---- .../arrowhead_adjustment/elk/sketch.exp.svg | 2 +- .../testdata/stable/chaos1/elk/board.exp.json | 2 +- .../testdata/stable/chaos1/elk/sketch.exp.svg | 4 +- .../testdata/stable/chaos2/elk/board.exp.json | 20 ++++---- .../testdata/stable/chaos2/elk/sketch.exp.svg | 6 +-- .../stable/investigate/elk/board.exp.json | 48 +++++++++---------- .../stable/investigate/elk/sketch.exp.svg | 6 +-- .../sequence_diagrams/elk/board.exp.json | 4 +- .../sequence_diagrams/elk/sketch.exp.svg | 2 +- 16 files changed, 98 insertions(+), 98 deletions(-) diff --git a/e2etests/testdata/stable/all_shapes/elk/board.exp.json b/e2etests/testdata/stable/all_shapes/elk/board.exp.json index 3d2556ad8..a89fff02d 100644 --- a/e2etests/testdata/stable/all_shapes/elk/board.exp.json +++ b/e2etests/testdata/stable/all_shapes/elk/board.exp.json @@ -752,7 +752,7 @@ "y": 392 }, { - "x": 854.5, + "x": 855, "y": 492 } ], @@ -827,7 +827,7 @@ "route": [ { "x": 1062, - "y": 378 + "y": 361 }, { "x": 1062, @@ -865,11 +865,11 @@ "labelPercentage": 0, "route": [ { - "x": 93.5, + "x": 93, "y": 138 }, { - "x": 93.5, + "x": 94, "y": 252 } ], @@ -904,11 +904,11 @@ "labelPercentage": 0, "route": [ { - "x": 93.5, + "x": 93, "y": 378 }, { - "x": 93.5, + "x": 94, "y": 492 } ], @@ -943,11 +943,11 @@ "labelPercentage": 0, "route": [ { - "x": 290.5, + "x": 291, "y": 138 }, { - "x": 290.5, + "x": 291, "y": 252 } ], @@ -982,11 +982,11 @@ "labelPercentage": 0, "route": [ { - "x": 290.5, + "x": 290, "y": 378 }, { - "x": 290.5, + "x": 291, "y": 492 } ], @@ -1099,12 +1099,12 @@ "labelPercentage": 0, "route": [ { - "x": 478.5, + "x": 478, "y": 138 }, { - "x": 478.5, - "y": 238 + "x": 479, + "y": 240 } ], "animated": false, diff --git a/e2etests/testdata/stable/all_shapes/elk/sketch.exp.svg b/e2etests/testdata/stable/all_shapes/elk/sketch.exp.svg index b6ca41575..7b2c4a56c 100644 --- a/e2etests/testdata/stable/all_shapes/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/all_shapes/elk/sketch.exp.svg @@ -18,7 +18,7 @@ width="1352" height="824" viewBox="-88 -88 1352 824">rectanglesquarepageparallelogramdocumentcylinderqueuepackagestepcalloutstored_datapersondiamondovalcirclehexagoncloud +rectanglesquarepageparallelogramdocumentcylinderqueuepackagestepcalloutstored_datapersondiamondovalcirclehexagoncloud rectanglesquarepageparallelogramdocumentcylinderqueuepackagestepcalloutstored_datapersondiamondovalcirclehexagoncloud +rectanglesquarepageparallelogramdocumentcylinderqueuepackagestepcalloutstored_datapersondiamondovalcirclehexagoncloud cba * +cba * aaadddeeebbbccc111 222 +aaadddeeebbbccc111 222 - + aabbllmm

nn

oocciikkdd

gg

hhjj

ee

-
ff1122 334455667788 +ff1122 334455667788 - + - + aabbccddllffwwyynniijjkkssuurmeemmmmgghhzzooppqqrrttvvxxabac 123456 +aabbccddllffwwyynniijjkkssuurmeemmmmgghhzzooppqqrrttvvxxabac 123456 - - + + diff --git a/e2etests/testdata/stable/sequence_diagrams/elk/board.exp.json b/e2etests/testdata/stable/sequence_diagrams/elk/board.exp.json index 3ed298e02..81a532b8a 100644 --- a/e2etests/testdata/stable/sequence_diagrams/elk/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagrams/elk/board.exp.json @@ -3565,7 +3565,7 @@ "route": [ { "x": 748, - "y": 176 + "y": 165 }, { "x": 748, @@ -3729,7 +3729,7 @@ "route": [ { "x": 830, - "y": 176 + "y": 165 }, { "x": 830, diff --git a/e2etests/testdata/stable/sequence_diagrams/elk/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagrams/elk/sketch.exp.svg index b043d6fdd..938982dd1 100644 --- a/e2etests/testdata/stable/sequence_diagrams/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagrams/elk/sketch.exp.svg @@ -18,7 +18,7 @@ width="3324" height="4389" viewBox="-88 -88 3324 4389">a_shapea_sequenceanotherfinallysequencesequencesequencescoreritemResponseitemessayRubricconceptitemOutcomescorerconceptessayRubricitemitemOutcomeitemResponsescoreritemResponseitemessayRubricconceptitemOutcome getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts)getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) +a_shapea_sequenceanotherfinallysequencesequencesequencescoreritemResponseitemessayRubricconceptitemOutcomescorerconceptessayRubricitemitemOutcomeitemResponsescoreritemResponseitemessayRubricconceptitemOutcome getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts)getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) From a0515da60b4582a00acd6deddd9e6bc5e46e48ce Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Sat, 17 Dec 2022 20:47:14 -0800 Subject: [PATCH 03/39] changelog --- ci/release/changelogs/next.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 14a6c2a39..10392f641 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -17,4 +17,5 @@ [https://github.com/terrastruct/d2/issues/415](https://github.com/terrastruct/d2/issues/415) - Fixed serialization affecting binary plugins (TALA). [https://github.com/terrastruct/d2/pull/426](https://github.com/terrastruct/d2/pull/426) +- Fixed connections in elk layouts not going all the way to shape borders. [https://github.com/terrastruct/d2/pull/459](https://github.com/terrastruct/d2/pull/459) - Fixed a connection rendering bug that could happen in firefox when there were no connection labels. [https://github.com/terrastruct/d2/pull/453](https://github.com/terrastruct/d2/pull/453) From 6e61645d0fadb40fe948a980ab8afb74db923e50 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Tue, 13 Dec 2022 23:40:14 -0800 Subject: [PATCH 04/39] ci: reorg aws --- ci/release/builders/{aws_copy_keys.sh => aws/copy-id.sh} | 0 ci/release/builders/{aws_ensure.sh => aws/ensure.sh} | 0 ci/release/builders/{ => aws}/ssh.sh | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename ci/release/builders/{aws_copy_keys.sh => aws/copy-id.sh} (100%) rename ci/release/builders/{aws_ensure.sh => aws/ensure.sh} (100%) rename ci/release/builders/{ => aws}/ssh.sh (100%) diff --git a/ci/release/builders/aws_copy_keys.sh b/ci/release/builders/aws/copy-id.sh similarity index 100% rename from ci/release/builders/aws_copy_keys.sh rename to ci/release/builders/aws/copy-id.sh diff --git a/ci/release/builders/aws_ensure.sh b/ci/release/builders/aws/ensure.sh similarity index 100% rename from ci/release/builders/aws_ensure.sh rename to ci/release/builders/aws/ensure.sh diff --git a/ci/release/builders/ssh.sh b/ci/release/builders/aws/ssh.sh similarity index 100% rename from ci/release/builders/ssh.sh rename to ci/release/builders/aws/ssh.sh From d23eb5b3327954f112af5296983ff5c57e6aaece Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Wed, 14 Dec 2022 00:47:07 -0800 Subject: [PATCH 05/39] ci: Prep for windows host --- ci/release/README.md | 4 +- ci/release/{builders => }/aws/ensure.sh | 65 +++++++++++++++++------ ci/release/{builders => }/aws/ssh.sh | 4 +- ci/release/build_docker.sh | 2 +- ci/release/builders/Dockerfile-centos | 16 ------ ci/release/builders/aws/copy-id.sh | 57 -------------------- ci/release/{builders => linux}/Dockerfile | 4 +- ci/sub | 2 +- 8 files changed, 56 insertions(+), 98 deletions(-) rename ci/release/{builders => }/aws/ensure.sh (83%) rename ci/release/{builders => }/aws/ssh.sh (91%) delete mode 100644 ci/release/builders/Dockerfile-centos delete mode 100755 ci/release/builders/aws/copy-id.sh rename ci/release/{builders => linux}/Dockerfile (77%) diff --git a/ci/release/README.md b/ci/release/README.md index 4530983e4..200e86a29 100644 --- a/ci/release/README.md +++ b/ci/release/README.md @@ -23,12 +23,12 @@ it depends on from ../sub/lib. > variables as we must compile d2 directly on each release target to include dagre. > See https://github.com/terrastruct/d2/issues/31 -Use `--host-only` to build only the release for the host's OS-ARCH pair. +Use `--host-only` to build only the release for the host's `$OS-$ARCH` pair. ### build_docker.sh Helper script called by build.sh to build D2 on each linux runner inside Docker. -The Dockerfile is in ./builders/Dockerfile +The Dockerfile is in ./linux/Dockerfile ### _build.sh diff --git a/ci/release/builders/aws/ensure.sh b/ci/release/aws/ensure.sh similarity index 83% rename from ci/release/builders/aws/ensure.sh rename to ci/release/aws/ensure.sh index 63c117abc..2013de91c 100755 --- a/ci/release/builders/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -1,11 +1,11 @@ #!/bin/sh set -eu -cd -- "$(dirname "$0")/../../.." -. ./ci/sub/lib.sh +. "$(dirname "$0")/../../../../ci/sub/lib.sh" +cd -- "$(dirname "$0")/../../../.." help() { cat </dev/null fi @@ -86,8 +101,8 @@ create_remote_hosts() { --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-amd64' \ | jq -r '.Reservations[].Instances[].PublicDnsName') if [ -n "$dnsname" ]; then - log "TSTRUCT_LINUX_AMD64_BUILDER=admin@$dnsname" - export TSTRUCT_LINUX_AMD64_BUILDER=admin@$dnsname + log "TSTRUCT_LINUX_AMD64_BUILDER=ubuntu@$dnsname" + export TSTRUCT_LINUX_AMD64_BUILDER=ubuntu@$dnsname break fi sleep 5 @@ -99,11 +114,12 @@ create_remote_hosts() { | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ - --image-id=ami-0e67506f183e5ab60 \ + --image-id=ami-06e2dea2cdda3acda \ --count=1 \ --instance-type=t4g.small \ --security-groups=ssh \ "--key-name=$KEY_NAME" \ + --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-linux-arm64}]"' \ '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-linux-arm64}]"' >/dev/null fi @@ -112,8 +128,8 @@ create_remote_hosts() { --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-arm64' \ | jq -r '.Reservations[].Instances[].PublicDnsName') if [ -n "$dnsname" ]; then - log "TSTRUCT_LINUX_ARM64_BUILDER=admin@$dnsname" - export TSTRUCT_LINUX_ARM64_BUILDER=admin@$dnsname + log "TSTRUCT_LINUX_ARM64_BUILDER=ubuntu@$dnsname" + export TSTRUCT_LINUX_ARM64_BUILDER=ubuntu@$dnsname break fi sleep 5 @@ -146,6 +162,7 @@ create_remote_hosts() { --instance-type=mac1.metal \ --security-groups=ssh \ "--key-name=$KEY_NAME" \ + --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ --placement "Tenancy=host,HostId=$MACOS_AMD64_HOST_ID" \ --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-macos-amd64}]"' \ '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-macos-amd64}]"' >/dev/null @@ -173,6 +190,7 @@ create_remote_hosts() { --instance-type=mac2.metal \ --security-groups=ssh \ "--key-name=$KEY_NAME" \ + --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ --placement "Tenancy=host,HostId=$MACOS_ARM64_HOST_ID" \ --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-macos-arm64}]"' \ '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-macos-arm64}]"' >/dev/null @@ -191,6 +209,8 @@ create_remote_hosts() { } init_remote_hosts() { + bigheader init_remote_hosts + header linux-amd64 REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER init_remote_linux header linux-arm64 @@ -201,15 +221,19 @@ init_remote_hosts() { REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER init_remote_macos FGCOLOR=2 header summary - log "export TSTRUCT_LINUX_AMD64_BUILDER=$TSTRUCT_LINUX_AMD64_BUILDER" - log "export TSTRUCT_LINUX_ARM64_BUILDER=$TSTRUCT_LINUX_ARM64_BUILDER" - log "export TSTRUCT_MACOS_AMD64_BUILDER=$TSTRUCT_MACOS_AMD64_BUILDER" - log "export TSTRUCT_MACOS_ARM64_BUILDER=$TSTRUCT_MACOS_ARM64_BUILDER" + echo "export TSTRUCT_LINUX_AMD64_BUILDER=$TSTRUCT_LINUX_AMD64_BUILDER" + echo "export TSTRUCT_LINUX_ARM64_BUILDER=$TSTRUCT_LINUX_ARM64_BUILDER" + echo "export TSTRUCT_MACOS_AMD64_BUILDER=$TSTRUCT_MACOS_AMD64_BUILDER" + echo "export TSTRUCT_MACOS_ARM64_BUILDER=$TSTRUCT_MACOS_ARM64_BUILDER" } init_remote_linux() { wait_remote_host + if [ -n "${ID_PUB_PATH-}" ]; then + sh_c ssh_copy_id -i="$ID_PUB_PATH" "$REMOTE_HOST" + fi + sh_c ssh "$REMOTE_HOST" sh -s -- < /dev/null sudo -E apt-get update -y sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin @@ -239,6 +263,11 @@ mkdir -p \$HOME/.local/share/man EOF init_remote_env + sh_c ssh "$REMOTE_HOST" sh -s -- </tmp/go.tar.gz -RUN tar -C /usr/local -xzf /tmp/go.tar.gz - -ENV PATH="/usr/local/go/bin:$PATH" - -RUN yum install -y rsync wget -RUN yum groupinstall -y 'Development Tools' - -RUN curl -fsSL https://ftp.gnu.org/gnu/gcc/gcc-5.2.0/gcc-5.2.0.tar.gz >/tmp/gcc.tar.gz -RUN tar -C /usr/local -xzf /tmp/gcc.tar.gz -RUN cd /usr/local/gcc-5.2.0 && ./contrib/download_prerequisites && mkdir -p build \ - && cd build && ../configure --disable-multilib && make && make install diff --git a/ci/release/builders/aws/copy-id.sh b/ci/release/builders/aws/copy-id.sh deleted file mode 100755 index cc0d548ef..000000000 --- a/ci/release/builders/aws/copy-id.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -set -eu -cd -- "$(dirname "$0")/../../.." -. ./ci/sub/lib.sh - -help() { - cat < .ssh/authorized_keys.dedup' - sh_c ssh "$REMOTE_HOST" 'cp .ssh/authorized_keys.dedup .ssh/authorized_keys' - sh_c ssh "$REMOTE_HOST" 'rm .ssh/authorized_keys.dedup' -} - -main "$@" diff --git a/ci/release/builders/Dockerfile b/ci/release/linux/Dockerfile similarity index 77% rename from ci/release/builders/Dockerfile rename to ci/release/linux/Dockerfile index 5adc0bd25..5bc66a568 100644 --- a/ci/release/builders/Dockerfile +++ b/ci/release/linux/Dockerfile @@ -8,5 +8,5 @@ RUN curl -fsSL "https://go.dev/dl/go$GOVERSION.tar.gz" >/tmp/go.tar.gz RUN tar -C /usr/local -xzf /tmp/go.tar.gz ENV PATH="/usr/local/go/bin:$PATH" -RUN apt-get install -y build-essential -RUN apt-get install -y rsync +RUN apt-get install -y build-essential \ + rsync diff --git a/ci/sub b/ci/sub index 7923b353a..d103a1954 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 7923b353a829cf289171baff0d0d017ae3d32278 +Subproject commit d103a19548c72d68d8aab26da1fda158489252ba From ece68225b178efa6510cb93a422bb0133c716868 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Thu, 15 Dec 2022 07:14:06 -0800 Subject: [PATCH 06/39] ci/release/aws: Setup windows instance --- ci/release/aws/ensure.sh | 335 ++++++++++++++++++++++++++++----------- ci/release/aws/ssh.sh | 13 +- ci/sub | 2 +- 3 files changed, 249 insertions(+), 101 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 2013de91c..c216ac0ac 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -1,11 +1,12 @@ #!/bin/sh set -eu -. "$(dirname "$0")/../../../../ci/sub/lib.sh" -cd -- "$(dirname "$0")/../../../.." +. "$(dirname "$0")/../../../ci/sub/lib.sh" +cd -- "$(dirname "$0")/../../.." help() { cat </dev/null \ | jq -r .SecurityGroups[0].GroupId) @@ -81,36 +90,61 @@ create_remote_hosts() { --cidr 0.0.0.0/0 >/dev/null fi + header windows-security-group + SG_ID=$(aws ec2 describe-security-groups --group-names windows 2>/dev/null \ + | jq -r .SecurityGroups[0].GroupId) + if [ -z "$SG_ID" ]; then + SG_ID=$(sh_c aws ec2 create-security-group \ + --group-name windows \ + --description windows \ + --vpc-id "$VPC_ID" | jq -r .GroupId) + fi + + header windows-security-group-ingress + SG_RULES_COUNT=$(aws ec2 describe-security-groups --group-names windows \ + | jq -r '.SecurityGroups[0].IpPermissions | length') + if [ "$SG_RULES_COUNT" -ne 2 ]; then + sh_c aws ec2 authorize-security-group-ingress \ + --group-id "$SG_ID" \ + --protocol tcp \ + --port 22 \ + --cidr 0.0.0.0/0 >/dev/null + sh_c aws ec2 authorize-security-group-ingress \ + --group-id "$SG_ID" \ + --protocol tcp \ + --port 3389 \ + --cidr 0.0.0.0/0 >/dev/null + fi +} + +create_linux_amd64() { header linux-amd64 + REMOTE_NAME=ci-d2-linux-amd64 state=$(aws ec2 describe-instances --filters \ - 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-amd64' \ + 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=ci-d2-linux-amd64' \ | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ --image-id=ami-0ecc74eca1d66d8a6 \ --count=1 \ - --instance-type=t2.small \ + --instance-type=t3.small \ --security-groups=ssh \ "--key-name=$KEY_NAME" \ --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ - --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-linux-amd64}]"' \ - '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-linux-amd64}]"' >/dev/null + --block-device-mappings '"DeviceName=/dev/sda1,Ebs={VolumeSize=64,VolumeType=gp3}"' \ + --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=ci-d2-linux-amd64}]"' \ + '"ResourceType=volume,Tags=[{Key=Name,Value=ci-d2-linux-amd64}]"' >/dev/null fi - while true; do - dnsname=$(sh_c aws ec2 describe-instances \ - --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-amd64' \ - | jq -r '.Reservations[].Instances[].PublicDnsName') - if [ -n "$dnsname" ]; then - log "TSTRUCT_LINUX_AMD64_BUILDER=ubuntu@$dnsname" - export TSTRUCT_LINUX_AMD64_BUILDER=ubuntu@$dnsname - break - fi - sleep 5 - done + wait_remote_host_ip + log "CI_D2_LINUX_AMD64=ubuntu@$ip" + export CI_D2_LINUX_AMD64=ubuntu@$ip +} +create_linux_arm64() { header linux-arm64 + REMOTE_NAME=ci-d2-linux-arm64 state=$(aws ec2 describe-instances --filters \ - 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-arm64' \ + 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=ci-d2-linux-arm64' \ | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ @@ -120,40 +154,28 @@ create_remote_hosts() { --security-groups=ssh \ "--key-name=$KEY_NAME" \ --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ - --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-linux-arm64}]"' \ - '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-linux-arm64}]"' >/dev/null + --block-device-mappings '"DeviceName=/dev/sda1,Ebs={VolumeSize=64,VolumeType=gp3}"' \ + --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=ci-d2-linux-arm64}]"' \ + '"ResourceType=volume,Tags=[{Key=Name,Value=ci-d2-linux-arm64}]"' >/dev/null fi - while true; do - dnsname=$(sh_c aws ec2 describe-instances \ - --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-arm64' \ - | jq -r '.Reservations[].Instances[].PublicDnsName') - if [ -n "$dnsname" ]; then - log "TSTRUCT_LINUX_ARM64_BUILDER=ubuntu@$dnsname" - export TSTRUCT_LINUX_ARM64_BUILDER=ubuntu@$dnsname - break - fi - sleep 5 - done + wait_remote_host_ip + log "CI_D2_LINUX_ARM64=ubuntu@$ip" + export CI_D2_LINUX_ARM64=ubuntu@$ip +} - header "macos-amd64-host" - MACOS_AMD64_HOST_ID=$(aws ec2 describe-hosts --filter 'Name=state,Values=pending,available' 'Name=tag:Name,Values=d2-builder-macos-amd64' | jq -r '.Hosts[].HostId') - if [ -z "$MACOS_AMD64_HOST_ID" ]; then - MACOS_AMD64_HOST_ID=$(sh_c aws ec2 allocate-hosts --instance-type mac1.metal --quantity 1 --availability-zone us-west-2a \ - --tag-specifications '"ResourceType=dedicated-host,Tags=[{Key=Name,Value=d2-builder-macos-amd64}]"' \ - | jq -r .HostIds[0]) - fi - - header "macos-arm64-host" - MACOS_ARM64_HOST_ID=$(aws ec2 describe-hosts --filter 'Name=state,Values=pending,available' 'Name=tag:Name,Values=d2-builder-macos-arm64' | jq -r '.Hosts[].HostId') - if [ -z "$MACOS_ARM64_HOST_ID" ]; then - MACOS_ARM64_HOST_ID=$(sh_c aws ec2 allocate-hosts --instance-type mac2.metal --quantity 1 --availability-zone us-west-2a \ - --tag-specifications '"ResourceType=dedicated-host,Tags=[{Key=Name,Value=d2-builder-macos-amd64}]"' \ +create_macos_amd64() { + header macos-amd64-host + MACOS_AMD64_ID=$(aws ec2 describe-hosts --filter 'Name=state,Values=pending,available' 'Name=tag:Name,Values=ci-d2-macos-amd64' | jq -r '.Hosts[].HostId') + if [ -z "$MACOS_AMD64_ID" ]; then + MACOS_AMD64_ID=$(sh_c aws ec2 allocate-hosts --instance-type mac1.metal --quantity 1 --availability-zone us-west-2a \ + --tag-specifications '"ResourceType=dedicated-host,Tags=[{Key=Name,Value=ci-d2-macos-amd64}]"' \ | jq -r .HostIds[0]) fi header macos-amd64 + REMOTE_NAME=ci-d2-macos-amd64 state=$(aws ec2 describe-instances --filters \ - 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-macos-amd64' \ + 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=ci-d2-macos-amd64' \ | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ @@ -163,25 +185,29 @@ create_remote_hosts() { --security-groups=ssh \ "--key-name=$KEY_NAME" \ --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ - --placement "Tenancy=host,HostId=$MACOS_AMD64_HOST_ID" \ - --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-macos-amd64}]"' \ - '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-macos-amd64}]"' >/dev/null + --placement "Tenancy=host,HostId=$MACOS_AMD64_ID" \ + --block-device-mappings '"DeviceName=/dev/sda1,Ebs={VolumeSize=100,VolumeType=gp3}"' \ + --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=ci-d2-macos-amd64}]"' \ + '"ResourceType=volume,Tags=[{Key=Name,Value=ci-d2-macos-amd64}]"' >/dev/null + fi + wait_remote_host_ip + log "CI_D2_MACOS_AMD64=ec2-user@$ip" + export CI_D2_MACOS_AMD64=ec2-user@$ip +} + +create_macos_arm64() { + header macos-arm64-host + MACOS_ARM64_ID=$(aws ec2 describe-hosts --filter 'Name=state,Values=pending,available' 'Name=tag:Name,Values=ci-d2-macos-arm64' | jq -r '.Hosts[].HostId') + if [ -z "$MACOS_ARM64_ID" ]; then + MACOS_ARM64_ID=$(sh_c aws ec2 allocate-hosts --instance-type mac2.metal --quantity 1 --availability-zone us-west-2a \ + --tag-specifications '"ResourceType=dedicated-host,Tags=[{Key=Name,Value=ci-d2-macos-amd64}]"' \ + | jq -r .HostIds[0]) fi - while true; do - dnsname=$(sh_c aws ec2 describe-instances \ - --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-macos-amd64' \ - | jq -r '.Reservations[].Instances[].PublicDnsName') - if [ -n "$dnsname" ]; then - log "TSTRUCT_MACOS_AMD64_BUILDER=ec2-user@$dnsname" - export TSTRUCT_MACOS_AMD64_BUILDER=ec2-user@$dnsname - break - fi - sleep 5 - done header macos-arm64 + REMOTE_NAME=ci-d2-macos-arm64 state=$(aws ec2 describe-instances --filters \ - 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-macos-arm64' \ + 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=ci-d2-macos-arm64' \ | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ @@ -191,48 +217,95 @@ create_remote_hosts() { --security-groups=ssh \ "--key-name=$KEY_NAME" \ --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ - --placement "Tenancy=host,HostId=$MACOS_ARM64_HOST_ID" \ - --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=d2-builder-macos-arm64}]"' \ - '"ResourceType=volume,Tags=[{Key=Name,Value=d2-builder-macos-arm64}]"' >/dev/null + --placement "Tenancy=host,HostId=$MACOS_ARM64_ID" \ + --block-device-mappings '"DeviceName=/dev/sda1,Ebs={VolumeSize=100,VolumeType=gp3}"' \ + --tag-specifications '"ResourceType=instance,Tags=[{Key=Name,Value=ci-d2-macos-arm64}]"' \ + '"ResourceType=volume,Tags=[{Key=Name,Value=ci-d2-macos-arm64}]"' >/dev/null fi + wait_remote_host_ip + log "CI_D2_MACOS_ARM64=ec2-user@$ip" + export CI_D2_MACOS_ARM64=ec2-user@$ip +} + +create_windows_amd64() { + header windows-amd64 + REMOTE_NAME=ci-d2-windows-amd64 + state=$(aws ec2 describe-instances --filters \ + 'Name=instance-state-name,Values=pending,running,stopping,stopped' "Name=tag:Name,Values=$REMOTE_NAME" \ + | jq -r '.Reservations[].Instances[].State.Name') + if [ -z "$state" ]; then + sh_c aws ec2 run-instances \ + --image-id=ami-0c5300e833c2b32f3 \ + --count=1 \ + --instance-type=t3.medium \ + --security-groups=windows \ + "--key-name=$KEY_NAME_WINDOWS" \ + --iam-instance-profile 'Name=AmazonSSMRoleForInstancesQuickSetup' \ + --block-device-mappings '"DeviceName=/dev/sda1,Ebs={VolumeSize=64,VolumeType=gp3}"' \ + --tag-specifications "'ResourceType=instance,Tags=[{Key=Name,Value=$REMOTE_NAME}]'" \ + "'ResourceType=volume,Tags=[{Key=Name,Value=$REMOTE_NAME}]'" >/dev/null + fi + wait_remote_host_ip + log "CI_D2_WINDOWS_AMD64=Administrator@$ip" + export CI_D2_WINDOWS_AMD64=Administrator@$ip +} + +wait_remote_host_ip() { while true; do - dnsname=$(sh_c aws ec2 describe-instances \ - --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-macos-arm64' \ - | jq -r '.Reservations[].Instances[].PublicDnsName') - if [ -n "$dnsname" ]; then - log "TSTRUCT_MACOS_ARM64_BUILDER=ec2-user@$dnsname" - export TSTRUCT_MACOS_ARM64_BUILDER=ec2-user@$dnsname + ip=$(sh_c aws ec2 describe-instances \ + --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' "Name=tag:Name,Values=$REMOTE_NAME" \ + | jq -r '.Reservations[].Instances[].PublicIpAddress') + if [ -n "$ip" ]; then + alloc_static_ip + ip=$(sh_c aws ec2 describe-instances \ + --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' "Name=tag:Name,Values=$REMOTE_NAME" \ + | jq -r '.Reservations[].Instances[].PublicIpAddress') break fi sleep 5 done } +alloc_static_ip() { + # No-op until our limit is increased. + return 0 + allocation_id=$(aws ec2 describe-addresses --filters "Name=tag:Name,Values=$REMOTE_NAME" | jq -r '.Addresses[].AllocationId') + if [ -z "$allocation_id" ]; then + sh_c aws ec2 allocate-address --tag-specifications "'ResourceType=elastic-ip,Tags=[{Key=Name,Value=$REMOTE_NAME}]'" + allocation_id=$(aws ec2 describe-addresses --filters "Name=tag:Name,Values=$REMOTE_NAME" | jq -r '.Addresses[].AllocationId') + fi + + instance_id=$(aws ec2 describe-instances \ + --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' "Name=tag:Name,Values=$REMOTE_NAME" \ + | jq -r '.Reservations[].Instances[].InstanceId') + aws ec2 associate-address --instance-id "$instance_id" --allocation-id "$allocation_id" +} + init_remote_hosts() { bigheader init_remote_hosts - header linux-amd64 - REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER init_remote_linux - header linux-arm64 - REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER init_remote_linux - header macos-amd64 - REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER init_remote_macos - header macos-arm64 - REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER init_remote_macos + JOBNAME=$JOBNAME/linux/amd64 runjob_filter REMOTE_HOST=$CI_D2_LINUX_AMD64 REMOTE_NAME=ci-d2-linux-amd64 init_remote_linux + JOBNAME=$JOBNAME/linux/arm64 runjob_filter REMOTE_HOST=$CI_D2_LINUX_ARM64 REMOTE_NAME=ci-d2-linux-arm64 init_remote_linux + JOBNAME=$JOBNAME/macos/amd64 runjob_filter REMOTE_HOST=$CI_D2_MACOS_AMD64 REMOTE_NAME=ci-d2-macos-amd64 init_remote_macos + JOBNAME=$JOBNAME/macos/arm64 runjob_filter REMOTE_HOST=$CI_D2_MACOS_ARM64 REMOTE_NAME=ci-d2-macos-arm64 init_remote_macos + JOBNAME=$JOBNAME/windows/amd64 runjob_filter REMOTE_HOST=$CI_D2_WINDOWS_AMD64 REMOTE_NAME=ci-d2-windows-amd64 init_remote_windows FGCOLOR=2 header summary - echo "export TSTRUCT_LINUX_AMD64_BUILDER=$TSTRUCT_LINUX_AMD64_BUILDER" - echo "export TSTRUCT_LINUX_ARM64_BUILDER=$TSTRUCT_LINUX_ARM64_BUILDER" - echo "export TSTRUCT_MACOS_AMD64_BUILDER=$TSTRUCT_MACOS_AMD64_BUILDER" - echo "export TSTRUCT_MACOS_ARM64_BUILDER=$TSTRUCT_MACOS_ARM64_BUILDER" + echo "export CI_D2_LINUX_AMD64=$CI_D2_LINUX_AMD64" + echo "export CI_D2_LINUX_ARM64=$CI_D2_LINUX_ARM64" + echo "export CI_D2_MACOS_AMD64=$CI_D2_MACOS_AMD64" + echo "export CI_D2_MACOS_ARM64=$CI_D2_MACOS_ARM64" + echo "export CI_D2_WINDOWS_AMD64=$CI_D2_WINDOWS_AMD64" + + # Windows and AWS SSM both defeated me. + FGCOLOR=3 bigheader "WARNING: WINDOWS INITIALIZATION MUST BE COMPLETED MANUALLY OVER RDP AND POWERSHELL!" } init_remote_linux() { + header "$REMOTE_NAME" wait_remote_host - if [ -n "${ID_PUB_PATH-}" ]; then - sh_c ssh_copy_id -i="$ID_PUB_PATH" "$REMOTE_HOST" - fi + sh_c ssh_copy_id -i="$ID_PUB_PATH" "$REMOTE_HOST" sh_c ssh "$REMOTE_HOST" sh -s -- < utf8: https://stackoverflow.com/a/34969243/4283659 +\$null = New-Item -Force "\$env:ProgramData\ssh\administrators_authorized_keys" -Value (Get-Content -Path "\$env:ProgramData\ssh\administrators_authorized_keys" | Out-String) +get-acl "\$env:ProgramData\ssh\ssh_host_rsa_key" | set-acl "\$env:ProgramData\ssh\administrators_authorized_keys" +EOF +) + + gen_init_ps1=$(cat <&2 + warn "2. RDP into $REMOTE_HOST and open PowerShell." + warn '3. Generate and execute C:\Users\Administrator\Desktop\init.ps1 with:' + printf '%s\n' "$gen_init_ps1" >&2 +} + main "$@" diff --git a/ci/release/aws/ssh.sh b/ci/release/aws/ssh.sh index 32d3765f7..387bdf38c 100755 --- a/ci/release/aws/ssh.sh +++ b/ci/release/aws/ssh.sh @@ -1,7 +1,7 @@ #!/bin/sh set -eu -. "$(dirname "$0")/../../../../ci/sub/lib.sh" -cd -- "$(dirname "$0")/../../../.." +. "$(dirname "$0")/../../../ci/sub/lib.sh" +cd -- "$(dirname "$0")/../../.." help() { cat < Date: Thu, 15 Dec 2022 19:55:50 -0800 Subject: [PATCH 07/39] ci/aws: Use static IPs again --- ci/release/aws/ensure.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index c216ac0ac..917daf84f 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -51,6 +51,13 @@ main() { JOBNAME=create runjob_filter create_remote_hosts JOBNAME=init && runjob_filter init_remote_hosts + + FGCOLOR=2 header summary + echo "export CI_D2_LINUX_AMD64=$CI_D2_LINUX_AMD64" + echo "export CI_D2_LINUX_ARM64=$CI_D2_LINUX_ARM64" + echo "export CI_D2_MACOS_AMD64=$CI_D2_MACOS_AMD64" + echo "export CI_D2_MACOS_ARM64=$CI_D2_MACOS_ARM64" + echo "export CI_D2_WINDOWS_AMD64=$CI_D2_WINDOWS_AMD64" } create_remote_hosts() { @@ -200,7 +207,7 @@ create_macos_arm64() { MACOS_ARM64_ID=$(aws ec2 describe-hosts --filter 'Name=state,Values=pending,available' 'Name=tag:Name,Values=ci-d2-macos-arm64' | jq -r '.Hosts[].HostId') if [ -z "$MACOS_ARM64_ID" ]; then MACOS_ARM64_ID=$(sh_c aws ec2 allocate-hosts --instance-type mac2.metal --quantity 1 --availability-zone us-west-2a \ - --tag-specifications '"ResourceType=dedicated-host,Tags=[{Key=Name,Value=ci-d2-macos-amd64}]"' \ + --tag-specifications '"ResourceType=dedicated-host,Tags=[{Key=Name,Value=ci-d2-macos-arm64}]"' \ | jq -r .HostIds[0]) fi @@ -267,8 +274,6 @@ wait_remote_host_ip() { } alloc_static_ip() { - # No-op until our limit is increased. - return 0 allocation_id=$(aws ec2 describe-addresses --filters "Name=tag:Name,Values=$REMOTE_NAME" | jq -r '.Addresses[].AllocationId') if [ -z "$allocation_id" ]; then sh_c aws ec2 allocate-address --tag-specifications "'ResourceType=elastic-ip,Tags=[{Key=Name,Value=$REMOTE_NAME}]'" @@ -290,13 +295,6 @@ init_remote_hosts() { JOBNAME=$JOBNAME/macos/arm64 runjob_filter REMOTE_HOST=$CI_D2_MACOS_ARM64 REMOTE_NAME=ci-d2-macos-arm64 init_remote_macos JOBNAME=$JOBNAME/windows/amd64 runjob_filter REMOTE_HOST=$CI_D2_WINDOWS_AMD64 REMOTE_NAME=ci-d2-windows-amd64 init_remote_windows - FGCOLOR=2 header summary - echo "export CI_D2_LINUX_AMD64=$CI_D2_LINUX_AMD64" - echo "export CI_D2_LINUX_ARM64=$CI_D2_LINUX_ARM64" - echo "export CI_D2_MACOS_AMD64=$CI_D2_MACOS_AMD64" - echo "export CI_D2_MACOS_ARM64=$CI_D2_MACOS_ARM64" - echo "export CI_D2_WINDOWS_AMD64=$CI_D2_WINDOWS_AMD64" - # Windows and AWS SSM both defeated me. FGCOLOR=3 bigheader "WARNING: WINDOWS INITIALIZATION MUST BE COMPLETED MANUALLY OVER RDP AND POWERSHELL!" } @@ -449,6 +447,8 @@ $(perl -pe 's#\n#\r\n#' "$ID_PUB_PATH" | jq -Rs .) # utf8BOM -> utf8: https://stackoverflow.com/a/34969243/4283659 \$null = New-Item -Force "\$env:ProgramData\ssh\administrators_authorized_keys" -Value (Get-Content -Path "\$env:ProgramData\ssh\administrators_authorized_keys" | Out-String) get-acl "\$env:ProgramData\ssh\ssh_host_rsa_key" | set-acl "\$env:ProgramData\ssh\administrators_authorized_keys" + +Restart-Computer EOF ) From 6fe4af1105b57af9e0b654af9e478d0f6aa9fd36 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Thu, 15 Dec 2022 22:49:26 -0800 Subject: [PATCH 08/39] ci: Build and push official Dockerfile Closes #76 --- ci/release/Dockerfile | 18 ++++++ ci/release/build.sh | 60 +++++++++++++------ ci/release/build/.dockerignore | 1 + .../{build_docker.sh => build_in_docker.sh} | 0 ci/release/changelogs/next.md | 13 ++-- ci/sub | 2 +- docs/INSTALL.md | 16 ++++- 7 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 ci/release/Dockerfile create mode 100644 ci/release/build/.dockerignore rename ci/release/{build_docker.sh => build_in_docker.sh} (100%) diff --git a/ci/release/Dockerfile b/ci/release/Dockerfile new file mode 100644 index 000000000..d195fa05b --- /dev/null +++ b/ci/release/Dockerfile @@ -0,0 +1,18 @@ +# https://hub.docker.com/repository/docker/terrastruct/d2 +FROM debian:latest + +ARG TARGETARCH + +COPY ./d2-*-linux-$TARGETARCH.tar.gz /tmp +RUN mkdir -p /usr/local/lib/d2 \ + && tar -C /usr/local/lib/d2 -xzf /tmp/d2-*-linux-"$TARGETARCH".tar.gz \ + && /usr/local/lib/d2/d2-*/scripts/install.sh \ + && rm -Rf /tmp/d2-*-linux-"$TARGETARCH".tar.gz + +WORKDIR /root/src +EXPOSE 8080 +ENV PORT 8080 +ENV HOST 0.0.0.0 +ENV BROWSER false + +ENTRYPOINT ["/usr/local/bin/d2"] diff --git a/ci/release/build.sh b/ci/release/build.sh index e10426b92..cbc63114b 100755 --- a/ci/release/build.sh +++ b/ci/release/build.sh @@ -20,11 +20,12 @@ Flags: changed something and need to force rebuild, use this flag. --local - By default build.sh uses \$TSTRUCT_MACOS_AMD64_BUILDER, \$TSTRUCT_MACOS_ARM64_BUILDER, - \$TSTRUCT_LINUX_AMD64_BUILDER and \$TSTRUCT_LINUX_ARM64_BUILDER to build the release + By default build.sh uses \$CI_D2_LINUX_AMD64, \$CI_D2_LINUX_ARM64, + \$CI_D2_MACOS_AMD64 and \$CI_D2_MACOS_ARM64 to build the release archives. It's required for now due to the following issue: - https://github.com/terrastruct/d2/issues/31 With --local, build.sh will cross compile - locally. warning: This is only for testing purposes, do not use in production! + https://github.com/terrastruct/d2/issues/31 + With --local, build.sh will cross compile locally. warning: This is only for testing + purposes, do not use in production! --host-only Use to build the release archive for the host OS-ARCH only. All logging is done to stderr @@ -45,6 +46,13 @@ Flags: --uninstall Ensure a release using --host-only and uninstall it. + +--push-docker + Push the built docker image. Unfortunately dockerx requires the multi-arch images be + pushed if required in the same invocation as build. dockerx cannot load multi-arch + images into the daemon for push later. It's not slow though to use --push-docker after + building the image as nearly all artifacts are cached. + Automatically set if called from release.sh EOF } @@ -69,7 +77,7 @@ main() { ;; run) flag_reqarg && shift "$FLAGSHIFT" - JOBFILTER="$FLAGARG" + JOBFILTER=$FLAGARG ;; host-only) flag_noarg && shift "$FLAGSHIFT" @@ -96,6 +104,10 @@ main() { HOST_ONLY=1 LOCAL=1 ;; + push-docker) + flag_noarg && shift "$FLAGSHIFT" + PUSH_DOCKER=1 + ;; *) flag_errusage "unrecognized flag $FLAGRAW" ;; @@ -108,10 +120,13 @@ main() { VERSION=${VERSION:-$(git_describe_ref)} BUILD_DIR=ci/release/build/$VERSION + sh_c mkdir -p "$BUILD_DIR" + sh_c rm -f ci/release/build/latest + sh_c ln -s "$VERSION" ci/release/build/latest if [ -n "${HOST_ONLY-}" ]; then ensure_os ensure_arch - runjob "$OS-$ARCH" "build" + runjob "$OS/$ARCH" "build" if [ -n "${INSTALL-}" ]; then sh_c make -sC "ci/release/build/$VERSION/$OS-$ARCH/d2-$VERSION" install @@ -121,13 +136,15 @@ main() { return 0 fi - runjob linux-amd64 'OS=linux ARCH=amd64 build' & - runjob linux-arm64 'OS=linux ARCH=arm64 build' & - runjob macos-amd64 'OS=macos ARCH=amd64 build' & - runjob macos-arm64 'OS=macos ARCH=arm64 build' & - runjob windows-amd64 'OS=windows ARCH=amd64 build' & - runjob windows-arm64 'OS=windows ARCH=arm64 build' & + runjob linux/amd64 'OS=linux ARCH=amd64 build' & + runjob linux/arm64 'OS=linux ARCH=arm64 build' & + runjob macos/amd64 'OS=macos ARCH=amd64 build' & + runjob macos/arm64 'OS=macos ARCH=arm64 build' & + runjob windows/amd64 'OS=windows ARCH=amd64 build' & + runjob windows/arm64 'OS=windows ARCH=arm64 build' & waitjobs + + runjob linux/dockerimage 'build_docker_image' } build() { @@ -148,10 +165,10 @@ build() { macos) case $ARCH in amd64) - REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER build_remote_macos + REMOTE_HOST=$CI_D2_MACOS_AMD64 build_remote_macos ;; arm64) - REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER build_remote_macos + REMOTE_HOST=$CI_D2_MACOS_ARM64 build_remote_macos ;; *) warn "no builder for OS=$OS ARCH=$ARCH, building locally..." @@ -162,10 +179,10 @@ build() { linux) case $ARCH in amd64) - REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER build_remote_linux + REMOTE_HOST=$CI_D2_LINUX_AMD64 build_remote_linux ;; arm64) - REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER build_remote_linux + REMOTE_HOST=$CI_D2_LINUX_ARM64 build_remote_linux ;; *) warn "no builder for OS=$OS ARCH=$ARCH, building locally..." @@ -218,13 +235,18 @@ VERSION=$VERSION \ OS=$OS \ ARCH=$ARCH \ ARCHIVE=$ARCHIVE \ -./src/d2/ci/release/build_docker.sh" +./src/d2/ci/release/build_in_docker.sh" sh_c mkdir -p "$HW_BUILD_DIR" sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE" )} -ssh() { - command ssh -o='StrictHostKeyChecking=accept-new' "$@" +build_docker_image() { + D2_DOCKER_IMAGE=${D2_DOCKER_IMAGE:-terrastruct/d2} + flags='--load' + if [ -n "${PUSH_DOCKER-}" -o -n "${RELEASE-}" ]; then + flags='--push --platform linux/amd64,linux/arm64' + fi + sh_c docker buildx build $flags -t "$D2_DOCKER_IMAGE:$VERSION" -t "$D2_DOCKER_IMAGE:latest" --build-arg "VERSION=$VERSION" -f ./ci/release/Dockerfile "./ci/release/build/$VERSION" } main "$@" diff --git a/ci/release/build/.dockerignore b/ci/release/build/.dockerignore new file mode 100644 index 000000000..73f0caa06 --- /dev/null +++ b/ci/release/build/.dockerignore @@ -0,0 +1 @@ +**/d2*/ diff --git a/ci/release/build_docker.sh b/ci/release/build_in_docker.sh similarity index 100% rename from ci/release/build_docker.sh rename to ci/release/build_in_docker.sh diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 14a6c2a39..fe8e4a5d6 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -1,8 +1,8 @@ #### Features 🚀 -- Diagram padding can now can be configured in the CLI (default 100px). - [https://github.com/terrastruct/d2/pull/431](https://github.com/terrastruct/d2/pull/431) +- Diagram padding can now can be configured in the CLI (default 100px). [https://github.com/terrastruct/d2/pull/431](https://github.com/terrastruct/d2/pull/431) - Connection label backgrounds can now be set with the `style.fill` keyword. [https://github.com/terrastruct/d2/pull/452](https://github.com/terrastruct/d2/pull/452) +- Add official Docker image. See [./docs/INSTALL.md#docker](./docs/INSTALL.md#docker). [#76](https://github.com/terrastruct/d2/issues/76) #### Improvements 🧹 @@ -11,10 +11,7 @@ #### Bugfixes ⛑️ -- Fixed crash when sequence diagrams had no messages. - [https://github.com/terrastruct/d2/pull/427](https://github.com/terrastruct/d2/pull/427) -- Fixed `constraint` keyword setting label. - [https://github.com/terrastruct/d2/issues/415](https://github.com/terrastruct/d2/issues/415) -- Fixed serialization affecting binary plugins (TALA). - [https://github.com/terrastruct/d2/pull/426](https://github.com/terrastruct/d2/pull/426) +- Fixed crash when sequence diagrams had no messages. [https://github.com/terrastruct/d2/pull/427](https://github.com/terrastruct/d2/pull/427) +- Fixed `constraint` keyword setting label. [https://github.com/terrastruct/d2/issues/415](https://github.com/terrastruct/d2/issues/415) +- Fixed serialization affecting binary plugins (TALA). [https://github.com/terrastruct/d2/pull/426](https://github.com/terrastruct/d2/pull/426) - Fixed a connection rendering bug that could happen in firefox when there were no connection labels. [https://github.com/terrastruct/d2/pull/453](https://github.com/terrastruct/d2/pull/453) diff --git a/ci/sub b/ci/sub index 2f309fd0e..93bb2df10 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 2f309fd0e35f323dfaafdd0075cc3da565fa630c +Subproject commit 93bb2df10f248a30142a651ec57ca64eb0e82e84 diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 30e31d7cd..1ed858250 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -216,9 +216,23 @@ under plain Windows. aka Windows Subsystem for Linux if that's what you prefer. Installation is just like any other Linux system. +## Docker + +https://hub.docker.com/repository/docker/terrastruct/d2 + +We publish `amd64` and `arm64` images based on `debian:latest` for each release. + +Example usage: + +```sh +echo 'x -> y' >helloworld.d2 +docker run --rm -it -u "$(id -u):$(id -g)" -v "$PWD:/root/src" \ + -p 127.0.0.1:8080:8080 terrastruct/d2 --watch helloworld.d2 +# Visit http://127.0.0.1:8080 +``` + ## Coming soon -- Docker image - rpm and deb packages - with repositories and standalone - homebrew core From 7310211eaf77d7ab3ed7e39490d39061fc7496b7 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Thu, 15 Dec 2022 23:56:40 -0800 Subject: [PATCH 09/39] ci/aws: Use powershell for ssh on windows msys2 just doesn't work when you're running a command noninteractively. No output is shown. And then using msys2's opensshd doesn't actually listen exposed. I was unable to connect on port 22 remotely but could locally in windows. :shrug: --- ci/release/README.md | 2 +- ci/release/aws/ensure.sh | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ci/release/README.md b/ci/release/README.md index 200e86a29..4f8b1a56d 100644 --- a/ci/release/README.md +++ b/ci/release/README.md @@ -2,7 +2,7 @@ ## _install.sh -The template for the install script in the root of the repository. +The template for the install script in the root of the d2 repository. ### gen_install.sh diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 917daf84f..9fd7b89ff 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -418,7 +418,7 @@ init_remote_windows() { Invoke-WebRequest -Uri "https://github.com/msys2/msys2-installer/releases/download/2022-10-28/msys2-x86_64-20221028.exe" -OutFile "./msys2-x86_64.exe" ./msys2-x86_64.exe install --default-answer --confirm-command --root C:\msys64 -C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noconfirm base-devel' +C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noconfirm base-devel vim' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'curl -fsSL https://d2lang.com/install.sh | sh -s -- --tala' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'd2 --version' @@ -448,6 +448,8 @@ $(perl -pe 's#\n#\r\n#' "$ID_PUB_PATH" | jq -Rs .) \$null = New-Item -Force "\$env:ProgramData\ssh\administrators_authorized_keys" -Value (Get-Content -Path "\$env:ProgramData\ssh\administrators_authorized_keys" | Out-String) get-acl "\$env:ProgramData\ssh\ssh_host_rsa_key" | set-acl "\$env:ProgramData\ssh\administrators_authorized_keys" +New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force + Restart-Computer EOF ) From 7187d2ffaae1ba4c931d19f6a2a35003df1617e2 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Fri, 16 Dec 2022 00:24:59 -0800 Subject: [PATCH 10/39] aws: Set $PATH for rsync on windows amazing --- ci/release/aws/ensure.sh | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 9fd7b89ff..6452ec7e1 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -418,10 +418,14 @@ init_remote_windows() { Invoke-WebRequest -Uri "https://github.com/msys2/msys2-installer/releases/download/2022-10-28/msys2-x86_64-20221028.exe" -OutFile "./msys2-x86_64.exe" ./msys2-x86_64.exe install --default-answer --confirm-command --root C:\msys64 -C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noconfirm base-devel vim' +C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noconfirm base-devel vim rsync' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'curl -fsSL https://d2lang.com/install.sh | sh -s -- --tala' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'd2 --version' +\$oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path +\$newpath = “\$oldpath;C:\msys64\usr\bin” +Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value \$newPath + Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.3 -OutFile .\microsoft.ui.xaml.2.7.3.zip Expand-Archive -Force .\microsoft.ui.xaml.2.7.3.zip Add-AppxPackage .\microsoft.ui.xaml.2.7.3\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx @@ -452,6 +456,26 @@ New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Wi Restart-Computer EOF + +# Use the following to get a pure MSYS2 shell: +# ssh -t "$CI_D2_WINDOWS_AMD64" 'C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64' +# Use the following to run a command in a pure MSYS2 shell: +# ssh "$CI_D2_WINDOWS_AMD64" 'C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c "echo hi"' + +# In case msys2 improves in the future and allows for noninteractive commands via ssh "$CI_D2_WINDOWS_AMD64" echo hi +# The following will set the OpenSSH shell to MSYS2 instead of PowerShell. +# But PowerShell as the default is better anyway as it gives us access to both the UNIX userspace and Windows tools like wix/dotnet/winget. +# < utf8: https://stackoverflow.com/a/34969243/4283659 +# \$null = New-Item -Force C:\msys64\sshd_default_shell.cmd -Value (Get-Content -Path C:\msys64\sshd_default_shell.cmd | Out-String) +# Set-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell -Value C:\msys64\sshd_default_shell.cmd +# EOF +# To undo: +# < Date: Fri, 16 Dec 2022 00:40:51 -0800 Subject: [PATCH 11/39] ci/aws: Format docs better --- ci/release/aws/ensure.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 6452ec7e1..c850e4315 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -462,15 +462,25 @@ EOF # Use the following to run a command in a pure MSYS2 shell: # ssh "$CI_D2_WINDOWS_AMD64" 'C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c "echo hi"' -# In case msys2 improves in the future and allows for noninteractive commands via ssh "$CI_D2_WINDOWS_AMD64" echo hi -# The following will set the OpenSSH shell to MSYS2 instead of PowerShell. -# But PowerShell as the default is better anyway as it gives us access to both the UNIX userspace and Windows tools like wix/dotnet/winget. +# In case MSYS2 improves in the future and allows for noninteractive commands the +# following will set the OpenSSH shell to MSYS2 instead of PowerShell. +# +# Right now, setting MSYS2 to the DefaultShell like this will make it start bash in +# interactive mode always. Even for ssh "$CI_D2_WINDOWS_AMD64" echo hi. And so you'll end +# up with a blank prompt on which to input commands instead of having it execute the +# command you passed in via ssh. +# +# PowerShell as the default is better anyway as it gives us access to both the UNIX +# userspace and Windows tools like wix/dotnet/winget. +# +# To set: # < utf8: https://stackoverflow.com/a/34969243/4283659 # \$null = New-Item -Force C:\msys64\sshd_default_shell.cmd -Value (Get-Content -Path C:\msys64\sshd_default_shell.cmd | Out-String) # Set-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell -Value C:\msys64\sshd_default_shell.cmd # EOF +# # To undo: # < Date: Fri, 16 Dec 2022 00:47:36 -0800 Subject: [PATCH 12/39] ci: fmt --- ci/release/template/scripts/lib.sh | 2 +- ci/sub | 2 +- docs/INSTALL.md | 1 + install.sh | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ci/release/template/scripts/lib.sh b/ci/release/template/scripts/lib.sh index 62ade2f89..699795908 100644 --- a/ci/release/template/scripts/lib.sh +++ b/ci/release/template/scripts/lib.sh @@ -273,7 +273,7 @@ header() { bigheader() { set -- "$(echo "$*" | sed "s/^/ * /")" - FGCOLOR=${FGCOLOR:-3} logp "/**************************************************************** + FGCOLOR=${FGCOLOR:-6} logp "/**************************************************************** $* ****************************************************************/" } diff --git a/ci/sub b/ci/sub index 93bb2df10..8a9efaf95 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 93bb2df10f248a30142a651ec57ca64eb0e82e84 +Subproject commit 8a9efaf950ea04010c7822080ada546225a130d0 diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 1ed858250..22b01fb19 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -16,6 +16,7 @@ You may install `d2` through any of the following methods. - Windows - MSYS2 - WSL +- Docker - Coming soon ## install.sh diff --git a/install.sh b/install.sh index bbe0ca02e..026f423c9 100755 --- a/install.sh +++ b/install.sh @@ -278,7 +278,7 @@ header() { bigheader() { set -- "$(echo "$*" | sed "s/^/ * /")" - FGCOLOR=${FGCOLOR:-3} logp "/**************************************************************** + FGCOLOR=${FGCOLOR:-6} logp "/**************************************************************** $* ****************************************************************/" } From 1e52115a6b1d3288a58ebbd054a4bbfe68fd70f0 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Fri, 16 Dec 2022 00:59:50 -0800 Subject: [PATCH 13/39] ci/aws: Document how to run a POSIX script on windows --- ci/release/aws/ensure.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index c850e4315..801261a0f 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -457,10 +457,14 @@ New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Wi Restart-Computer EOF -# Use the following to get a pure MSYS2 shell: -# ssh -t "$CI_D2_WINDOWS_AMD64" 'C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64' -# Use the following to run a command in a pure MSYS2 shell: +# To run a POSIX script: +# ssh "$CI_D2_WINDOWS_AMD64" sh -s -- < Date: Fri, 16 Dec 2022 01:53:06 -0800 Subject: [PATCH 14/39] ci/aws/windows: Bootstrap into the vastly superior PowerShell v7 --- ci/release/aws/ensure.sh | 58 +++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 801261a0f..95f1acbbc 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -416,35 +416,41 @@ init_remote_windows() { init_ps1=$(cat < Date: Fri, 16 Dec 2022 02:20:07 -0800 Subject: [PATCH 15/39] ci/aws/windows: Only update $PATH if required --- ci/release/aws/ensure.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 95f1acbbc..19a1a9e97 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -466,9 +466,19 @@ C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noc C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'curl -fsSL https://d2lang.com/install.sh | sh -s -- --tala' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'd2 --version' -\$oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path -\$newpath = "\$oldpath;C:\msys64\usr\bin" -Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value \$newPath +\$path = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path).Path +if (\$path -notlike '*C:\msys64\usr\bin*') { + \$path = "\$path;C:\msys64\usr\bin" + Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value \$path +} +if (\$path -notlike '*C:\msys64\usr\local\bin*') { + \$path = "\$path;C:\msys64\usr\local\bin" + Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value \$path + Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value '' +} +(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path).Path + +Restart-Computer EOF # To run a POSIX script: From 888fa88009c4cbae71a74d65b4f42990b2c6dba3 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Fri, 16 Dec 2022 02:52:37 -0800 Subject: [PATCH 16/39] ci/release/aws: Minor fixes and improvements --- ci/release/aws/ensure.sh | 8 ++++++-- ci/sub | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 19a1a9e97..9c013ccce 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -386,6 +386,7 @@ init_remote_env() { } wait_remote_host() { + ssh-keygen -R "${REMOTE_HOST##*@}" while true; do if sh_c ssh "$REMOTE_HOST" true; then break @@ -402,7 +403,7 @@ wait_remote_host_windows() { while true; do if sh_c aws ssm start-session --target "$instance_id" \ --document-name 'AWS-StartNonInteractiveCommand' \ - --parameters "'{\"command\": [\"echo true; exit\"]}'"; then + --parameters "'{\"command\": [\"echo true\"]}'"; then break fi sleep 5 @@ -474,7 +475,6 @@ if (\$path -notlike '*C:\msys64\usr\bin*') { if (\$path -notlike '*C:\msys64\usr\local\bin*') { \$path = "\$path;C:\msys64\usr\local\bin" Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value \$path - Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value '' } (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path).Path @@ -531,6 +531,10 @@ EOF warn "2. RDP into $REMOTE_HOST and open PowerShell." warn '3. Generate and execute C:\Users\Administrator\Desktop\init.ps1 with:' printf '%s\n' "$gen_init_ps1" >&2 + warn '4. Run the following to be notified once installation is successful:' + cat < Date: Fri, 16 Dec 2022 03:06:14 -0800 Subject: [PATCH 17/39] ci/aws/windows: Use 5s sleep instead of 2s for glory command --- ci/release/aws/ensure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 9c013ccce..eda43283c 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -533,7 +533,7 @@ EOF printf '%s\n' "$gen_init_ps1" >&2 warn '4. Run the following to be notified once installation is successful:' cat < Date: Fri, 16 Dec 2022 03:13:51 -0800 Subject: [PATCH 18/39] ci/aws/windows: Improved examples --- ci/release/aws/ensure.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index eda43283c..66cc1cb1b 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -483,10 +483,10 @@ EOF # To run a POSIX script: # ssh "$CI_D2_WINDOWS_AMD64" sh -s -- < Date: Sun, 18 Dec 2022 07:30:09 -0800 Subject: [PATCH 19/39] ci/release/msi: Complete --- ci/release/build.sh | 25 +++++++++++++++++++++- ci/release/windows/.gitignore | 1 + ci/release/windows/d2.ico | Bin 0 -> 97144 bytes ci/release/windows/d2.png | Bin 0 -> 14509 bytes ci/release/windows/d2.wxs | 39 ++++++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 ci/release/windows/.gitignore create mode 100644 ci/release/windows/d2.ico create mode 100644 ci/release/windows/d2.png create mode 100644 ci/release/windows/d2.wxs diff --git a/ci/release/build.sh b/ci/release/build.sh index cbc63114b..82da752e3 100755 --- a/ci/release/build.sh +++ b/ci/release/build.sh @@ -144,7 +144,9 @@ main() { runjob windows/arm64 'OS=windows ARCH=arm64 build' & waitjobs - runjob linux/dockerimage 'build_docker_image' + runjob linux/dockerimage 'OS=linux build_docker_image' & + runjob windows/amd64/msi 'OS=windows ARCH=amd64 build_windows_msi' & + waitjobs } build() { @@ -249,4 +251,25 @@ build_docker_image() { sh_c docker buildx build $flags -t "$D2_DOCKER_IMAGE:$VERSION" -t "$D2_DOCKER_IMAGE:latest" --build-arg "VERSION=$VERSION" -f ./ci/release/Dockerfile "./ci/release/build/$VERSION" } +build_windows_msi() { + REMOTE_HOST=$CI_D2_WINDOWS_AMD64 + + ln -sf "../build/$VERSION/windows-amd64/d2-$VERSION/bin/d2.exe" ./ci/release/windows/d2.exe + sh_c rsync --archive --human-readable --copy-links --delete ./ci/release/windows/ "'$REMOTE_HOST:windows\'" + if ! echo "$VERSION" | grep '[0-9]\.[0-9].[0-9]'; then + WIX_VERSION=0.0.0 + else + WIX_VERSION=$VERSION + fi + sh_c ssh "$REMOTE_HOST" "'cd .\\windows && wix build -arch x64 -d D2Version=$WIX_VERSION .\d2.wxs'" + + # --files-from shouldn't be necessary but for some reason selecting d2.msi directly + # makes rsync error with: + # ERROR: rejecting unrequested file-list name: .\\windows\\d2.msi + # rsync error: requested action not supported (code 4) at flist.c(1027) [Receiver=3.2.7] + rsync_files=$(mktempd)/rsync-files + echo d2.msi >$rsync_files + sh_c rsync --archive --human-readable --files-from "$rsync_files" "'$REMOTE_HOST:windows\\'" "./ci/release/build/$VERSION/d2-$VERSION-$OS-$ARCH.msi" +} + main "$@" diff --git a/ci/release/windows/.gitignore b/ci/release/windows/.gitignore new file mode 100644 index 000000000..55ae023fc --- /dev/null +++ b/ci/release/windows/.gitignore @@ -0,0 +1 @@ +d2.exe diff --git a/ci/release/windows/d2.ico b/ci/release/windows/d2.ico new file mode 100644 index 0000000000000000000000000000000000000000..bc8335225a64ffe7e3820e01eec0de140ef87d03 GIT binary patch literal 97144 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 + + + + + + + + + + + + + + + + + + + + + + + + From e3e889f90d7290c3a150540fcb72192af80de620 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 10:18:23 -0800 Subject: [PATCH 20/39] docs/INSTALL.md: Document msi installer Closes #379 --- ci/release/changelogs/next.md | 3 ++- docs/INSTALL.md | 28 ++++++++-------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index fe8e4a5d6..58d3c237e 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -3,10 +3,11 @@ - Diagram padding can now can be configured in the CLI (default 100px). [https://github.com/terrastruct/d2/pull/431](https://github.com/terrastruct/d2/pull/431) - Connection label backgrounds can now be set with the `style.fill` keyword. [https://github.com/terrastruct/d2/pull/452](https://github.com/terrastruct/d2/pull/452) - Add official Docker image. See [./docs/INSTALL.md#docker](./docs/INSTALL.md#docker). [#76](https://github.com/terrastruct/d2/issues/76) +- Add `.msi` installer for convenient installation on Windows. [#379](https://github.com/terrastruct/d2/issues/379) #### Improvements 🧹 -- Fmt now preserves leading comment spacing. +- `d2 fmt` now preserves leading comment spacing. [#400](https://github.com/terrastruct/d2/issues/400) #### Bugfixes ⛑️ diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 22b01fb19..5a603afe3 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -175,31 +175,19 @@ binary. ## Windows -d2 builds and runs on Windows: +We have prebuilt releases of d2 available for Windows via `.msi` installers. The installer +will add the `d2` binary to your `$PATH` so that you can execute `d2` in `cmd.exe` or +`pwsh.exe`. -We have prebuilt standalone releases for Windows though they're structured in the same way -as our Unix releases. +### Release archives -Easiest way to use d2 on Windows is to just `chdir` into the bin directory of the release -and invoke d2 like `./d2 ` - -For installation, you'll have to put the `bin/d2.exe` binary into your `$PATH` or add the -`bin` directory of the release into your `$PATH`. - -See https://www.wikihow.com/Change-the-PATH-Environment-Variable-on-Windows - -Then you'll be able to call `d2` from the commandline in `cmd.exe` or `pwsh.exe`. - -We intend to have a `.msi` release installer sometime soon that handles putting `d2` into -your `$PATH` for you. - -### MSYS2 +We also have release archives for Windows structured in the same way as our Unix releases +for use with MSYS2. Screenshot 2022-12-06 at 2 55 27 AM -We recommend using [MSYS2](https://www.msys2.org/) or [Git -Bash](https://gitforwindows.org/#bash) (Git Bash is based on MSYS2) for an improved -terminal experience. +See [MSYS2](https://www.msys2.org/) or [Git Bash](https://gitforwindows.org/#bash) (Git +Bash is based on MSYS2). MSYS2 provides a unix style shell environment that is native to Windows (unlike [Cygwin](https://www.cygwin.com/)). MSYS2 allows `install.sh` to work, enables automatic From b76ab9b989f75a48320f808dfa1f0ef78077478b Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 10:36:20 -0800 Subject: [PATCH 21/39] fmt --- ci/release/windows/d2.wxs | 78 +++++++++++++++++++-------------------- docs/INSTALL.md | 2 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/ci/release/windows/d2.wxs b/ci/release/windows/d2.wxs index 3c49ba200..1b7b46631 100644 --- a/ci/release/windows/d2.wxs +++ b/ci/release/windows/d2.wxs @@ -1,39 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 5a603afe3..8141d9fc3 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -14,7 +14,7 @@ You may install `d2` through any of the following methods. - From source - Source Release - Windows - - MSYS2 + - Release archives - WSL - Docker - Coming soon From cffb29c9195e6e80e51105e56d7a67d43a36230a Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 10:48:57 -0800 Subject: [PATCH 22/39] d2: Add trailing newline to svg output The convention. Also makes log messages clearer when input/output is - as without the newline, you get this occasionally: success: successfully compiled - to - --- main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.go b/main.go index f37c40c0a..ce2af7899 100644 --- a/main.go +++ b/main.go @@ -243,6 +243,10 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, pad, if err != nil { return svg, false, err } + } else { + if len(out) > 0 && out[len(out)-1] != '\n' { + out = append(out, '\n') + } } err = ms.WritePath(outputPath, out) From 4a5a02a4cc2e5842da9e7eb388e84225c5a1f7b8 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 11:22:37 -0800 Subject: [PATCH 23/39] ci/sub: Update --- ci/sub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/sub b/ci/sub index 55bf1d39f..21542934c 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 55bf1d39f3d524804422d4bdb4559cd6ff151b49 +Subproject commit 21542934c5318ad3acab232bd15ef50e458663c6 From 54e2f870d2b9139e21788c92e7af9f6ea01e7f6a Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 11:32:20 -0800 Subject: [PATCH 24/39] ci/aws: Fix env on ubuntu --- ci/release/aws/ensure.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 66cc1cb1b..d5de7dfca 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -381,6 +381,9 @@ init_remote_env() { if sh_c ssh "$REMOTE_HOST" uname | grep -qF Darwin; then sh_c ssh "$REMOTE_HOST" "sudo launchctl stop com.openssh.sshd" else + # ubuntu has $PATH hard coded in /etc/environment for some reason. It takes precedence + # over ~/.ssh/environment. + sh_c ssh "$REMOTE_HOST" "sudo rm /etc/environment" sh_c ssh "$REMOTE_HOST" "sudo systemctl restart sshd" fi } From 72c0b76a22e12fc2639af011ad5350e39403c318 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 11:45:48 -0800 Subject: [PATCH 25/39] ci/aws: Copy SSH keys onto macOS hosts --- ci/release/aws/ensure.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index d5de7dfca..fb61f4725 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -347,6 +347,8 @@ init_remote_macos() { header "$REMOTE_NAME" wait_remote_host + sh_c ssh_copy_id -i="$ID_PUB_PATH" "$REMOTE_HOST" + sh_c ssh "$REMOTE_HOST" '"/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""' if sh_c ssh "$REMOTE_HOST" uname -m | grep -qF arm64; then From 84d732f804cdb55f9bddf28556d401d908947363 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 11:49:22 -0800 Subject: [PATCH 26/39] release/README.md: Update Windows template to reflect .msi installer --- ci/release/template/README.md.sh | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/ci/release/template/README.md.sh b/ci/release/template/README.md.sh index 7ccea6fb2..d08a71bf6 100755 --- a/ci/release/template/README.md.sh +++ b/ci/release/template/README.md.sh @@ -20,27 +20,11 @@ EOF if [ "$OS" = windows ]; then cat <\` - -For installation you'll have to add the \`./bin/d2.exe\` binary to your \`\$PATH\`. Or add -the \`./bin\` directory of this release to your \`\$PATH\`. - -See https://www.wikihow.com/Change-the-PATH-Environment-Variable-on-Windows - -Then you'll be able to call \`d2\` from the commandline in \`cmd.exe\` or \`pwsh.exe\`. - -We intend to have a \`.msi\` release installer sometime soon that handles putting \`d2.exe\` into +You may find our \`.msi\` installer more convenient as it handles putting \`d2.exe\` into your \`\$PATH\` for you. -You can also use \`make install\` to install on Windows after first installing -[MSYS2](https://www.msys2.org/) which emulates a Linux shell for Windows. Its terminal -also enables \`d2\` to show colors in its output. The manpage will also become accessible -with \`man d2\`. - See https://github.com/terrastruct/d2/blob/master/docs/INSTALL.md#windows EOF fi From ef73cce63bc5e14b38bd6d1ba6dc9a0eeb7bb79e Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:22:33 -0800 Subject: [PATCH 27/39] ci/aws: Install man-db on windows --- ci/release/aws/ensure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index fb61f4725..4ff4e1ee6 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -468,7 +468,7 @@ if (-Not (Test-Path -Path C:\msys64)) { Invoke-WebRequest -Uri "https://github.com/msys2/msys2-installer/releases/download/2022-10-28/msys2-x86_64-20221028.exe" -OutFile "./msys2-x86_64.exe" ./msys2-x86_64.exe install --default-answer --confirm-command --root C:\msys64 } -C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noconfirm base-devel vim rsync' +C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'pacman -Sy --noconfirm base-devel vim rsync man' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'curl -fsSL https://d2lang.com/install.sh | sh -s -- --tala' C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c 'd2 --version' From 908ccaf50c5ad54ad5040c8a4f1db3a9c0f7f0ef Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:24:11 -0800 Subject: [PATCH 28/39] ci/sub: Update [ci-force] --- ci/sub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/sub b/ci/sub index 21542934c..2f443c093 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 21542934c5318ad3acab232bd15ef50e458663c6 +Subproject commit 2f443c093f402bcc971eddec8abea1f385fa13e0 From f7d63213c758010b47349d25fba5decb5b41d6c2 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:26:58 -0800 Subject: [PATCH 29/39] fmt --- docs/CONTRIBUTING.md | 21 ++++++++------------- main.go | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index f5b08f6b1..801917b2b 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,19 +1,14 @@ # Contributing - -- [CI](#ci) -- [Flow](#flow) -- [Logistics](#logistics) -- [Dev](#dev) - * [Content](#content) - * [Tests](#tests) - + [Running tests](#running-tests) - + [Chaos tests](#chaos-tests) - * [Documentation](#documentation) - * [Questions](#questions) - - +- CI +- Flow +- Logistics +- Dev + - Content + - Tests + - Documentation + - Questions ## CI diff --git a/main.go b/main.go index ce2af7899..53ef5d201 100644 --- a/main.go +++ b/main.go @@ -244,7 +244,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, pad, return svg, false, err } } else { - if len(out) > 0 && out[len(out)-1] != '\n' { + if len(out) > 0 && out[len(out)-1] != '\n' { out = append(out, '\n') } } From b2b1382d58f5bed419a0ac8bb1777af9d5f07d4c Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:28:14 -0800 Subject: [PATCH 30/39] ci/sub: Update [ci-force] --- ci/sub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/sub b/ci/sub index 2f443c093..8c1b0bba1 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 2f443c093f402bcc971eddec8abea1f385fa13e0 +Subproject commit 8c1b0bba1d2539a11fc2b3f4fcf054d1d71f05a5 From d21a923f1f716585b5d6b73bf73b9652af36ec53 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:30:19 -0800 Subject: [PATCH 31/39] changelog: Fix wrapping --- ci/release/changelogs/next.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 58d3c237e..15c92e332 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -7,8 +7,7 @@ #### Improvements 🧹 -- `d2 fmt` now preserves leading comment spacing. - [#400](https://github.com/terrastruct/d2/issues/400) +- `d2 fmt` now preserves leading comment spacing. [#400](https://github.com/terrastruct/d2/issues/400) #### Bugfixes ⛑️ From 112c0a0d7d81fb73f702e8be1c4e5589014e6a9c Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:33:42 -0800 Subject: [PATCH 32/39] deps: update [ci-base] [ci-force] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 74e905dbd..7a7910207 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 gonum.org/v1/plot v0.12.0 nhooyr.io/websocket v1.8.7 - oss.terrastruct.com/util-go v0.0.0-20221213112904-c09378905bfb + oss.terrastruct.com/util-go v0.0.0-20221218203331-558e3b4adc95 ) require ( diff --git a/go.sum b/go.sum index fb6710cf6..e77eb6d53 100644 --- a/go.sum +++ b/go.sum @@ -806,8 +806,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -oss.terrastruct.com/util-go v0.0.0-20221213112904-c09378905bfb h1:ybqEeDAI/VyaVgPd5kis5aq+IPhHI3dQmdSxFG6SuuY= -oss.terrastruct.com/util-go v0.0.0-20221213112904-c09378905bfb/go.mod h1:Fwy72FDIOOM4K8F96ScXkxHHppR1CPfUyo9+x9c1PBU= +oss.terrastruct.com/util-go v0.0.0-20221218203331-558e3b4adc95 h1:Ya/jgBNhNwZ30BsEcyjf2bTT8dtCdTM2WOSMEeSGB3E= +oss.terrastruct.com/util-go v0.0.0-20221218203331-558e3b4adc95/go.mod h1:Fwy72FDIOOM4K8F96ScXkxHHppR1CPfUyo9+x9c1PBU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= From 72dfbf708f328f6c236176daba78d536fde5a425 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:41:22 -0800 Subject: [PATCH 33/39] ci/release/build.sh: Automatically clone ci submodule --- ci/release/build.sh | 7 ++++++- make.sh | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ci/release/build.sh b/ci/release/build.sh index 82da752e3..82f930a51 100755 --- a/ci/release/build.sh +++ b/ci/release/build.sh @@ -1,7 +1,12 @@ #!/bin/sh set -eu +if [ ! -e "$(dirname "$0")/../../ci/sub/.git" ]; then + set -x + git submodule update --init + set +x +fi +. "$(dirname "$0")/../../ci/sub/lib.sh" cd -- "$(dirname "$0")/../.." -. ./ci/sub/lib.sh help() { cat < Date: Sun, 18 Dec 2022 12:42:50 -0800 Subject: [PATCH 34/39] docs/INSTALL.md: Document minimum Go version required --- docs/INSTALL.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 8141d9fc3..410c95f77 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -158,6 +158,8 @@ You can always install from source: go install oss.terrastruct.com/d2@latest ``` +You need at least Go v1.18 + ### Source Release To install a release from source clone the repository and then: @@ -173,6 +175,8 @@ fonts and icons. Furthermore, when installing a non versioned commit, installing will ensure that `d2 --version` works correctly by embedding the commit hash into the `d2` binary. +Remember, you need at least Go v1.18 + ## Windows We have prebuilt releases of d2 available for Windows via `.msi` installers. The installer From be92906d9ad85ddb21227917164b4b1c384ab0a5 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 12:50:12 -0800 Subject: [PATCH 35/39] ci/release/aws: Reorder some statments [ci-force] --- ci/release/aws/ensure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 4ff4e1ee6..4c4020da5 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -383,10 +383,10 @@ init_remote_env() { if sh_c ssh "$REMOTE_HOST" uname | grep -qF Darwin; then sh_c ssh "$REMOTE_HOST" "sudo launchctl stop com.openssh.sshd" else + sh_c ssh "$REMOTE_HOST" "sudo systemctl restart sshd" # ubuntu has $PATH hard coded in /etc/environment for some reason. It takes precedence # over ~/.ssh/environment. sh_c ssh "$REMOTE_HOST" "sudo rm /etc/environment" - sh_c ssh "$REMOTE_HOST" "sudo systemctl restart sshd" fi } From 8f69f49f8b133431dfc68a6366b45cca849a08e6 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 18 Dec 2022 19:44:35 -0800 Subject: [PATCH 36/39] ci/aws: Use ssh-keygen in better spot --- ci/release/aws/ensure.sh | 4 ++-- ci/sub | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/release/aws/ensure.sh b/ci/release/aws/ensure.sh index 4c4020da5..5f68e45b3 100755 --- a/ci/release/aws/ensure.sh +++ b/ci/release/aws/ensure.sh @@ -267,6 +267,7 @@ wait_remote_host_ip() { ip=$(sh_c aws ec2 describe-instances \ --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' "Name=tag:Name,Values=$REMOTE_NAME" \ | jq -r '.Reservations[].Instances[].PublicIpAddress') + ssh-keygen -R "$ip" break fi sleep 5 @@ -391,7 +392,6 @@ init_remote_env() { } wait_remote_host() { - ssh-keygen -R "${REMOTE_HOST##*@}" while true; do if sh_c ssh "$REMOTE_HOST" true; then break @@ -538,7 +538,7 @@ EOF printf '%s\n' "$gen_init_ps1" >&2 warn '4. Run the following to be notified once installation is successful:' cat < Date: Sun, 18 Dec 2022 20:03:07 -0800 Subject: [PATCH 37/39] fix sequence edge identify --- d2layouts/d2sequence/layout.go | 2 +- d2layouts/d2sequence/sequence_diagram.go | 4 +- e2etests/regression_test.go | 12 + .../dagre/board.exp.json | 529 ++++++++++++++++++ .../dagre/sketch.exp.svg | 28 + .../elk/board.exp.json | 520 +++++++++++++++++ .../elk/sketch.exp.svg | 28 + 7 files changed, 1120 insertions(+), 3 deletions(-) create mode 100644 e2etests/testdata/regression/sequence_diagram_name_crash/dagre/board.exp.json create mode 100644 e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/regression/sequence_diagram_name_crash/elk/board.exp.json create mode 100644 e2etests/testdata/regression/sequence_diagram_name_crash/elk/sketch.exp.svg diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index 42efeb174..55192ceab 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -88,7 +88,7 @@ func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiag var edges []*d2graph.Edge for _, edge := range g.Edges { // both Src and Dst must be inside the sequence diagram - if strings.HasPrefix(edge.Src.AbsID(), obj.AbsID()) && strings.HasPrefix(edge.Dst.AbsID(), obj.AbsID()) { + if obj == g.Root || (strings.HasPrefix(edge.Src.AbsID(), obj.AbsID()+".") && strings.HasPrefix(edge.Dst.AbsID(), obj.AbsID()+".")) { edges = append(edges, edge) } } diff --git a/d2layouts/d2sequence/sequence_diagram.go b/d2layouts/d2sequence/sequence_diagram.go index b05ea10a6..258428975 100644 --- a/d2layouts/d2sequence/sequence_diagram.go +++ b/d2layouts/d2sequence/sequence_diagram.go @@ -466,8 +466,8 @@ func (sd *sequenceDiagram) routeMessages() error { } else { return fmt.Errorf("could not find center of %s", message.Dst.AbsID()) } - isToDescendant := strings.HasPrefix(message.Dst.AbsID(), message.Src.AbsID()) - isFromDescendant := strings.HasPrefix(message.Src.AbsID(), message.Dst.AbsID()) + isToDescendant := strings.HasPrefix(message.Dst.AbsID(), message.Src.AbsID()+".") + isFromDescendant := strings.HasPrefix(message.Src.AbsID(), message.Dst.AbsID()+".") isSelfMessage := message.Src == message.Dst if isSelfMessage || isToDescendant || isFromDescendant { diff --git a/e2etests/regression_test.go b/e2etests/regression_test.go index 7c627be74..b9c2399f1 100644 --- a/e2etests/regression_test.go +++ b/e2etests/regression_test.go @@ -40,6 +40,18 @@ b.1 -> b.1`, a: A b: B`, }, + { + name: "sequence_diagram_name_crash", + script: `foo: { + shape: sequence_diagram + a -> b +} +foobar: { + shape: sequence_diagram + c -> d +} +foo -> foobar`, + }, } runa(t, tcs) diff --git a/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/board.exp.json b/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/board.exp.json new file mode 100644 index 000000000..c07f75069 --- /dev/null +++ b/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/board.exp.json @@ -0,0 +1,529 @@ +{ + "name": "", + "shapes": [ + { + "id": "foo", + "type": "sequence_diagram", + "pos": { + "x": 0, + "y": 0 + }, + "width": 448, + "height": 520, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "foo", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 43, + "labelHeight": 41, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "foobar", + "type": "sequence_diagram", + "pos": { + "x": 0, + "y": 620 + }, + "width": 448, + "height": 520, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "foobar", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 84, + "labelHeight": 41, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "foo.a", + "type": "", + "pos": { + "x": 24, + "y": 110 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 12, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "foo.b", + "type": "", + "pos": { + "x": 274, + "y": 110 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "foobar.c", + "type": "", + "pos": { + "x": 24, + "y": 730 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 12, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "foobar.d", + "type": "", + "pos": { + "x": 274, + "y": 730 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [ + { + "id": "foo.(a -> b)[0]", + "src": "foo.a", + "srcArrow": "none", + "srcLabel": "", + "dst": "foo.b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 99, + "y": 366 + }, + { + "x": 349, + "y": 366 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 4 + }, + { + "id": "foobar.(c -> d)[0]", + "src": "foobar.c", + "srcArrow": "none", + "srcLabel": "", + "dst": "foobar.d", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 99, + "y": 986 + }, + { + "x": 349, + "y": 986 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 4 + }, + { + "id": "(foo -> foobar)[0]", + "src": "foo", + "srcArrow": "none", + "srcLabel": "", + "dst": "foobar", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 224, + "y": 520 + }, + { + "x": 224, + "y": 560 + }, + { + "x": 224, + "y": 580 + }, + { + "x": 224, + "y": 620 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(foo.a -- )[0]", + "src": "foo.a", + "srcArrow": "none", + "srcLabel": "", + "dst": "a-lifeline-end-2251863791", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 99, + "y": 236 + }, + { + "x": 99, + "y": 496 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + }, + { + "id": "(foo.b -- )[0]", + "src": "foo.b", + "srcArrow": "none", + "srcLabel": "", + "dst": "b-lifeline-end-668380428", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 349, + "y": 236 + }, + { + "x": 349, + "y": 496 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + }, + { + "id": "(foobar.c -- )[0]", + "src": "foobar.c", + "srcArrow": "none", + "srcLabel": "", + "dst": "c-lifeline-end-955173837", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 99, + "y": 856 + }, + { + "x": 99, + "y": 1116 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + }, + { + "id": "(foobar.d -- )[0]", + "src": "foobar.d", + "srcArrow": "none", + "srcLabel": "", + "dst": "d-lifeline-end-2106864010", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 349, + "y": 856 + }, + { + "x": 349, + "y": 1116 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + } + ] +} diff --git a/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg b/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg new file mode 100644 index 000000000..bdebbd687 --- /dev/null +++ b/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg @@ -0,0 +1,28 @@ + +foofoobarabcd \ No newline at end of file diff --git a/e2etests/testdata/regression/sequence_diagram_name_crash/elk/board.exp.json b/e2etests/testdata/regression/sequence_diagram_name_crash/elk/board.exp.json new file mode 100644 index 000000000..49186256a --- /dev/null +++ b/e2etests/testdata/regression/sequence_diagram_name_crash/elk/board.exp.json @@ -0,0 +1,520 @@ +{ + "name": "", + "shapes": [ + { + "id": "foo", + "type": "sequence_diagram", + "pos": { + "x": 12, + "y": 12 + }, + "width": 448, + "height": 520, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "foo", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 43, + "labelHeight": 41, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "foobar", + "type": "sequence_diagram", + "pos": { + "x": 12, + "y": 632 + }, + "width": 448, + "height": 520, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "foobar", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 84, + "labelHeight": 41, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "foo.a", + "type": "", + "pos": { + "x": 36, + "y": 122 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 12, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "foo.b", + "type": "", + "pos": { + "x": 286, + "y": 122 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "foobar.c", + "type": "", + "pos": { + "x": 36, + "y": 742 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 12, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "foobar.d", + "type": "", + "pos": { + "x": 286, + "y": 742 + }, + "width": 150, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [ + { + "id": "foo.(a -> b)[0]", + "src": "foo.a", + "srcArrow": "none", + "srcLabel": "", + "dst": "foo.b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 111, + "y": 378 + }, + { + "x": 361, + "y": 378 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 4 + }, + { + "id": "foobar.(c -> d)[0]", + "src": "foobar.c", + "srcArrow": "none", + "srcLabel": "", + "dst": "foobar.d", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 111, + "y": 998 + }, + { + "x": 361, + "y": 998 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 4 + }, + { + "id": "(foo -> foobar)[0]", + "src": "foo", + "srcArrow": "none", + "srcLabel": "", + "dst": "foobar", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 236, + "y": 532 + }, + { + "x": 236, + "y": 632 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(foo.a -- )[0]", + "src": "foo.a", + "srcArrow": "none", + "srcLabel": "", + "dst": "a-lifeline-end-2251863791", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 111, + "y": 248 + }, + { + "x": 111, + "y": 508 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + }, + { + "id": "(foo.b -- )[0]", + "src": "foo.b", + "srcArrow": "none", + "srcLabel": "", + "dst": "b-lifeline-end-668380428", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 361, + "y": 248 + }, + { + "x": 361, + "y": 508 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + }, + { + "id": "(foobar.c -- )[0]", + "src": "foobar.c", + "srcArrow": "none", + "srcLabel": "", + "dst": "c-lifeline-end-955173837", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 111, + "y": 868 + }, + { + "x": 111, + "y": 1128 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + }, + { + "id": "(foobar.d -- )[0]", + "src": "foobar.d", + "srcArrow": "none", + "srcLabel": "", + "dst": "d-lifeline-end-2106864010", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 6, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 361, + "y": 868 + }, + { + "x": 361, + "y": 1128 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 1 + } + ] +} diff --git a/e2etests/testdata/regression/sequence_diagram_name_crash/elk/sketch.exp.svg b/e2etests/testdata/regression/sequence_diagram_name_crash/elk/sketch.exp.svg new file mode 100644 index 000000000..1675c4f07 --- /dev/null +++ b/e2etests/testdata/regression/sequence_diagram_name_crash/elk/sketch.exp.svg @@ -0,0 +1,28 @@ + +foofoobarabcd \ No newline at end of file From e423c1a439b9e0cd4b8d96387b8a77cd92d56a54 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sun, 18 Dec 2022 20:04:26 -0800 Subject: [PATCH 38/39] add changelog --- ci/release/changelogs/next.md | 1 + .../sequence_diagram_name_crash/dagre/sketch.exp.svg | 5 ++++- .../sequence_diagram_name_crash/elk/sketch.exp.svg | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 15c92e332..44728f188 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -15,3 +15,4 @@ - Fixed `constraint` keyword setting label. [https://github.com/terrastruct/d2/issues/415](https://github.com/terrastruct/d2/issues/415) - Fixed serialization affecting binary plugins (TALA). [https://github.com/terrastruct/d2/pull/426](https://github.com/terrastruct/d2/pull/426) - Fixed a connection rendering bug that could happen in firefox when there were no connection labels. [https://github.com/terrastruct/d2/pull/453](https://github.com/terrastruct/d2/pull/453) +- Fixed a crash when external connection IDs were prefixes of a sequence diagram ID. [https://github.com/terrastruct/d2/pull/462](https://github.com/terrastruct/d2/pull/462) diff --git a/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg b/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg index bdebbd687..7b7c06c7c 100644 --- a/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg +++ b/e2etests/testdata/regression/sequence_diagram_name_crash/dagre/sketch.exp.svg @@ -18,7 +18,10 @@ width="648" height="1340" viewBox="-100 -100 648 1340">foofoobarabcd foofoobarabcd + + +foofoobarabcd foofoobarabcd + + +