Skip to content

Commit

Permalink
fix: tip requires "go install" since go1.20, and go1.18 to compile
Browse files Browse the repository at this point in the history
then "go install" mode available since go1.16.

In fact only 1.17.3 is required to compile, but say 1.18 to simplify.

Rework tip installation using GOROOT_BOOTSTRAP even on windows since
golang/dl@984e19f

Signed-off-by: Maxime Soulé <[email protected]>
  • Loading branch information
maxatome committed May 25, 2023
1 parent 0f78807 commit 6d63a7d
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 38 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
echo "--------------------"
false
fi
chmod -R u+w xxx
rm -rf xxx
elif [ -z "$GOROOT" ]; then
echo "GOROOT not available in environment"
Expand Down Expand Up @@ -85,6 +86,7 @@ jobs:
echo "*** GOPATH incorrectly set: '$GOPATH'"
false
fi
chmod -R u+w xxx
rm -rf xxx
- name: Test GOROOT_X_Y_X64 version with -p
Expand All @@ -108,9 +110,10 @@ jobs:
echo "*** GITHUB_ENV file is empty"
false
fi
chmod -R u+w xxx
rm -rf xxx
- name: Test last version with --dont-alter-github-path --dont-alter-github-env
- name: Test old version with --dont-alter-github-path --dont-alter-github-env
run: |
mkdir xxx
./install-go.pl --dont-alter-github-path --dont-alter-github-env 1.15.x xxx
Expand Down Expand Up @@ -146,6 +149,7 @@ jobs:
echo "*** GITHUB_ENV file is empty"
false
fi
chmod -R u+w zzz
rm -rf zzz
mv GITHUB_PATH.prev "$GITHUB_ENV"
Expand All @@ -163,4 +167,5 @@ jobs:
echo "*** GITHUB_ENV file is empty"
false
fi
chmod -R u+w zzz xxx
rm -rf zzz xxx
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
steps:
- name: Setup go
run: |
curl -sL https://raw.githubusercontent.com/maxatome/install-go/v3.3/install-go.pl |
curl -sL https://raw.githubusercontent.com/maxatome/install-go/v3.4/install-go.pl |
perl - ${{ matrix.go-version }} $HOME/go
- name: Checkout code
Expand Down
135 changes: 99 additions & 36 deletions install-go.pl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use strict;
use warnings;
use 5.010;
use version 0.77;

use JSON::PP;
use HTTP::Tiny;
Expand Down Expand Up @@ -83,35 +84,52 @@
}
elsif (system('which go') == 0)
{
chomp($goroot = `go env GOROOT`);
$goroot = go_env('go', 'GOROOT');
}

# If go is already installed somewhere, no need to install it
if ($goroot)
# If go is already installed somewhere *and* ≥ 1.18, no need to install it
if ($goroot and go_version("$goroot/bin/go") ge v1.18)
{
my $goroot_tip = install_tip($goroot, $DESTDIR);
export_env("$DESTDIR/go", $goroot_tip);
exit 0;
}

$TARGET = '1.17.x';
$TARGET = '1.18.x';
$TIP = 1;
}


# 1.12.3 -> (1.12.3, undef)
# 1.15.x -> (1.15, 4)
# "1.12.3" -> ("1.12.3", undef)
# "1.15.x" -> ("1.15", 4)
($TARGET, my $last_minor) = resolve_target($TARGET);

my $goroot_env;
link_go_if_available($TARGET, $last_minor, $DESTDIR)
or $goroot_env = install_go(get_url($TARGET, $last_minor), $DESTDIR, $TIP);
if ($TIP)
{
if (my $goroot = is_github_go_available($TARGET, $last_minor))
{
$goroot_env = install_tip($goroot, $DESTDIR);
}
else
{
$goroot_env = install_go(get_url($TARGET, $last_minor), $DESTDIR, 1);
}
}
else
{
link_github_go_if_available($TARGET, $last_minor, $DESTDIR)
or $goroot_env = install_go(get_url($TARGET, $last_minor), $DESTDIR);
}

export_env("$DESTDIR/go", $goroot_env);

exit 0;


# resolve_target retrieves official tags from golang repository then:
# "1.12.3" -> ("1.12.3", undef)
# "1.15.x" -> ("1.15, 4")
sub resolve_target
{
my $target = shift;
Expand All @@ -132,7 +150,7 @@ sub resolve_target
}
else
{
die "Bad target $target, should be 1.12 or 1.12.1 or 1.12.x\n"
die "Bad target $target, should be 1.12 or 1.12.1 or 1.12.x or tip\n"
}

my $r = http_get('https://go.googlesource.com/go/+refs/tags?format=JSON');
Expand Down Expand Up @@ -164,43 +182,57 @@ sub resolve_target
}

# Github images provide sometimes some go versions. If one of them
# matches, link it instead of downloading a new one.
# matches, returns its GOROOT.
#
# Win env:
# GOROOT=C:\hostedtoolcache\windows\go\1.14.10\x64
# GOROOT_1_10_X64=C:\hostedtoolcache\windows\go\1.10.8\x64
# returns C:\hostedtoolcache\windows\go\1.10.8\x64
#
# Linux env:
# GOROOT=/opt/hostedtoolcache/go/1.14.10/x64
# GOROOT_1_11_X64=/opt/hostedtoolcache/go/1.11.13/x64
sub link_go_if_available
# returns /opt/hostedtoolcache/go/1.11.13/x64
sub is_github_go_available
{
my($target, $last_minor, $dest_dir) = @_;
my($target, $last_minor) = @_;

my $full = $target;
$full .= ".$last_minor" if defined $last_minor;
$target .= ".$last_minor" if defined $last_minor;

my $vreg = qr,go[\\/]\Q$full\E[\\/]x64\z,;
my $vreg = qr,go[\\/]\Q$target\E[\\/]x64\z,;
while (my($var, $value) = each %ENV)
{
if ($var =~ /^GOROOT(?:_\d+_\d+_X64)?\z/
and $value =~ $vreg
and -f -x "$value/bin/go")
{
say "Find already installed go version $full";
mkdir_p("$dest_dir/go");
foreach my $subdir (qw(bin src pkg))
{
symlink("$value/$subdir", "$dest_dir/go/$subdir")
or die "symlink($value/$subdir, $dest_dir/go/$subdir): $!\n";
}
say "go version $full symlinked and available as $dest_dir/go/bin/go";
return 1;
return $value;
}
}
return;
}

# Github images provide sometimes some go versions. If one of them
# matches, link it instead of downloading a new one.
sub link_github_go_if_available
{
my($target, $last_minor, $dest_dir) = @_;

$target .= ".$last_minor" if defined $last_minor;

my $goroot = is_github_go_available($target) or return;

say "Find already installed go version $target";
mkdir_p("$dest_dir/go");
foreach my $subdir (qw(bin src pkg))
{
symlink("$goroot/$subdir", "$dest_dir/go/$subdir")
or die "symlink($goroot/$subdir, $dest_dir/go/$subdir): $!\n";
}
say "go version $target symlinked and available as $dest_dir/go/bin/go";
return 1;
}

sub get_url
{
my($target, $last_minor) = @_;
Expand Down Expand Up @@ -241,7 +273,7 @@ sub install_go
if ($EXT eq 'zip')
{
exe(qw(curl -L -s -o x.zip), $url);
exe(qw(unzip x.zip go/bin/* go/pkg/**/* go/src/**/*));
exe(qw(unzip -q x.zip go/bin/* go/pkg/**/* go/src/**/*));
unlink 'x.zip';
}
else
Expand All @@ -252,6 +284,7 @@ sub install_go
my $goroot_env;
if ($tip)
{
say "go $version installed as $dest_dir/go/bin/go to build tip";
$goroot_env = install_tip("$dest_dir/go", $dest_dir);
}
else
Expand All @@ -267,18 +300,23 @@ sub install_tip
my($goroot, $dest_dir) = @_;

my $gopath = "$dest_dir/go/gopath";
my $go = "$goroot/bin/go";
mkdir_p($gopath);
{
my $go = "$goroot/bin/go";

local $ENV{GOPATH} = $gopath;
local $ENV{GOROOT} = $goroot;
exe($go, 'version');
exe($go, qw(get golang.org/dl/gotip));
my $goversion = go_version($go);
say "Compiling tip using $goversion ($go)";
exe($go, qw(install golang.org/dl/gotip@latest));
}

my $gotip = "$gopath/bin/gotip";
exe($gotip, 'download');
my $gotip;
{
local $ENV{GOROOT_BOOTSTRAP} = $goroot;
$gotip = "$gopath/bin/gotip";
say "$gotip download (GOROOT_BOOTSTRAP=$ENV{GOROOT_BOOTSTRAP})";
exe($gotip, 'download');
}

my $final_go = "$dest_dir/go/bin/go";
if (-e $final_go)
Expand All @@ -298,8 +336,7 @@ sub install_tip
return do
{
delete local $ENV{GOROOT};
chomp(my $goroot_env = `$gotip env GOROOT`);
$goroot_env;
go_env($gotip, 'GOROOT');
};
}

Expand Down Expand Up @@ -348,8 +385,7 @@ sub install_prebuilt_tip
return do
{
delete local $ENV{GOROOT};
chomp(my $goroot_env = `$dest_dir/go/bin/go env GOROOT`);
$goroot_env;
go_env("$dest_dir/go/bin/go", "GOROOT");
};
}

Expand Down Expand Up @@ -449,7 +485,7 @@ sub mkdir_p
my $up = $dir =~ s,[\\/]*[^\\/]+[\\/]*\z,,r;
mkdir_p($up) if $up ne '';

mkdir $dir or d $dir or die "Cannot create $dir: $!\n";
mkdir $dir or -d $dir or die "Cannot create $dir: $!\n";
}

my $use_curl;
Expand Down Expand Up @@ -542,3 +578,30 @@ sub http_head

return HTTP::Tiny::->new->head($url);
}

sub go_version
{
my $go = shift;

open(my $fh, '-|', $go, 'version') or die "Cannot fork $go version: $!\n";
chomp(my $goversion = <$fh>);
close $fh;

if ($goversion =~ /^go version go([\d.]+) /
and my $v = eval { version->parse("v$1") })
{
return $v;
}
return v0;
}

sub go_env
{
my $go = shift;

open(my $fh, '-|', $go, env => @_) or die "Cannot fork $go env @_: $!\n";
chomp(my $res = <$fh>);
close $fh;

return $res;
}

0 comments on commit 6d63a7d

Please sign in to comment.