@@ -7,6 +7,7 @@ package runner
7
7
import (
8
8
"context"
9
9
"fmt"
10
+ "os"
10
11
"path"
11
12
"path/filepath"
12
13
"strings"
@@ -87,7 +88,108 @@ func (DebianRunner) Prepare(ctx context.Context, sshClient SSHClient, logger Log
87
88
88
89
// Copy places the required files on the host.
89
90
func (DebianRunner ) Copy (ctx context.Context , sshClient SSHClient , logger Logger , repoArchive string , builds []Build ) error {
90
- return linuxCopy (ctx , sshClient , logger , repoArchive , builds )
91
+ // copy the archive and extract it on the host
92
+ logger .Logf ("Copying repo" )
93
+ destRepoName := filepath .Base (repoArchive )
94
+ err := sshClient .Copy (repoArchive , destRepoName )
95
+ if err != nil {
96
+ return fmt .Errorf ("failed to SCP repo archive %s: %w" , repoArchive , err )
97
+ }
98
+
99
+ // remove build paths, on cases where the build path is different from agent.
100
+ for _ , build := range builds {
101
+ for _ , remoteBuildPath := range []string {build .Path , build .SHA512Path } {
102
+ relativeAgentDir := filepath .Join ("agent" , remoteBuildPath )
103
+ _ , _ , err := sshClient .Exec (ctx , "sudo" , []string {"rm" , "-rf" , relativeAgentDir }, nil )
104
+ // doesn't need to be a fatal error.
105
+ if err != nil {
106
+ logger .Logf ("error removing build dir %s: %w" , relativeAgentDir , err )
107
+ }
108
+ }
109
+ }
110
+
111
+ // ensure that agent directory is removed (possible it already exists if instance already used)
112
+ stdout , stderr , err := sshClient .Exec (ctx ,
113
+ "sudo" , []string {"rm" , "-rf" , "agent" }, nil )
114
+ if err != nil {
115
+ return fmt .Errorf (
116
+ "failed to remove agent directory before unziping new one: %w. stdout: %q, stderr: %q" ,
117
+ err , stdout , stderr )
118
+ }
119
+
120
+ stdOut , errOut , err := sshClient .Exec (ctx , "unzip" , []string {destRepoName , "-d" , "agent" }, nil )
121
+ if err != nil {
122
+ return fmt .Errorf ("failed to unzip %s to agent directory: %w (stdout: %s, stderr: %s)" , destRepoName , err , stdOut , errOut )
123
+ }
124
+
125
+ // prepare for testing
126
+ logger .Logf ("Running make mage and prepareOnRemote" )
127
+ envs := `GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH"`
128
+ installMage := strings .NewReader (fmt .Sprintf (`cd agent && %s make mage && %s mage integration:prepareOnRemote` , envs , envs ))
129
+ stdOut , errOut , err = sshClient .Exec (ctx , "bash" , nil , installMage )
130
+ if err != nil {
131
+ return fmt .Errorf ("failed to perform make mage and prepareOnRemote: %w (stdout: %s, stderr: %s)" , err , stdOut , errOut )
132
+ }
133
+
134
+ // determine if the build needs to be replaced on the host
135
+ // if it already exists and the SHA512 are the same contents, then
136
+ // there is no reason to waste time uploading the build
137
+ for _ , build := range builds {
138
+ copyBuild := true
139
+ localSHA512 , err := os .ReadFile (build .SHA512Path )
140
+ if err != nil {
141
+ return fmt .Errorf ("failed to read local SHA52 contents %s: %w" , build .SHA512Path , err )
142
+ }
143
+ hostSHA512Path := filepath .Base (build .SHA512Path )
144
+ hostSHA512 , err := sshClient .GetFileContents (ctx , hostSHA512Path )
145
+ if err == nil {
146
+ if string (localSHA512 ) == string (hostSHA512 ) {
147
+ logger .Logf ("Skipping copy agent build %s; already the same" , filepath .Base (build .Path ))
148
+ copyBuild = false
149
+ }
150
+ }
151
+
152
+ if copyBuild {
153
+ // ensure the existing copies are removed first
154
+ toRemove := filepath .Base (build .Path )
155
+ stdOut , errOut , err = sshClient .Exec (ctx ,
156
+ "sudo" , []string {"rm" , "-f" , toRemove }, nil )
157
+ if err != nil {
158
+ return fmt .Errorf ("failed to remove %q: %w (stdout: %q, stderr: %q)" ,
159
+ toRemove , err , stdOut , errOut )
160
+ }
161
+
162
+ toRemove = filepath .Base (build .SHA512Path )
163
+ stdOut , errOut , err = sshClient .Exec (ctx ,
164
+ "sudo" , []string {"rm" , "-f" , toRemove }, nil )
165
+ if err != nil {
166
+ return fmt .Errorf ("failed to remove %q: %w (stdout: %q, stderr: %q)" ,
167
+ toRemove , err , stdOut , errOut )
168
+ }
169
+
170
+ logger .Logf ("Copying agent build %s" , filepath .Base (build .Path ))
171
+ }
172
+
173
+ for _ , buildPath := range []string {build .Path , build .SHA512Path } {
174
+ if copyBuild {
175
+ err = sshClient .Copy (buildPath , filepath .Base (buildPath ))
176
+ if err != nil {
177
+ return fmt .Errorf ("failed to SCP build %s: %w" , filepath .Base (buildPath ), err )
178
+ }
179
+ }
180
+ insideAgentDir := filepath .Join ("agent" , buildPath )
181
+ stdOut , errOut , err = sshClient .Exec (ctx , "mkdir" , []string {"-p" , filepath .Dir (insideAgentDir )}, nil )
182
+ if err != nil {
183
+ return fmt .Errorf ("failed to create %s directory: %w (stdout: %s, stderr: %s)" , filepath .Dir (insideAgentDir ), err , stdOut , errOut )
184
+ }
185
+ stdOut , errOut , err = sshClient .Exec (ctx , "ln" , []string {filepath .Base (buildPath ), insideAgentDir }, nil )
186
+ if err != nil {
187
+ return fmt .Errorf ("failed to hard link %s to %s: %w (stdout: %s, stderr: %s)" , filepath .Base (buildPath ), insideAgentDir , err , stdOut , errOut )
188
+ }
189
+ }
190
+ }
191
+
192
+ return nil
91
193
}
92
194
93
195
// Run the test
@@ -140,7 +242,39 @@ func (DebianRunner) Run(ctx context.Context, verbose bool, sshClient SSHClient,
140
242
141
243
// Diagnostics gathers any diagnostics from the host.
142
244
func (DebianRunner ) Diagnostics (ctx context.Context , sshClient SSHClient , logger Logger , destination string ) error {
143
- return linuxDiagnostics (ctx , sshClient , logger , destination )
245
+ // take ownership, as sudo tests will create with root permissions (allow to fail in the case it doesn't exist)
246
+ diagnosticDir := "$HOME/agent/build/diagnostics"
247
+ _ , _ , _ = sshClient .Exec (ctx , "sudo" , []string {"chown" , "-R" , "$USER:$USER" , diagnosticDir }, nil )
248
+ stdOut , _ , err := sshClient .Exec (ctx , "ls" , []string {"-1" , diagnosticDir }, nil )
249
+ if err != nil {
250
+ //nolint:nilerr // failed to list the directory, probably don't have any diagnostics (do nothing)
251
+ return nil
252
+ }
253
+ eachDiagnostic := strings .Split (string (stdOut ), "\n " )
254
+ for _ , filename := range eachDiagnostic {
255
+ filename = strings .TrimSpace (filename )
256
+ if filename == "" {
257
+ continue
258
+ }
259
+
260
+ // don't use filepath.Join as we need this to work in Windows as well
261
+ // this is because if we use `filepath.Join` on a Windows host connected to a Linux host
262
+ // it will use a `\` and that will be incorrect for Linux
263
+ fp := fmt .Sprintf ("%s/%s" , diagnosticDir , filename )
264
+ // use filepath.Join on this path because it's a path on this specific host platform
265
+ dp := filepath .Join (destination , filename )
266
+ logger .Logf ("Copying diagnostic %s" , filename )
267
+ out , err := os .Create (dp )
268
+ if err != nil {
269
+ return fmt .Errorf ("failed to create file %s: %w" , dp , err )
270
+ }
271
+ err = sshClient .GetFileContentsOutput (ctx , fp , out )
272
+ _ = out .Close ()
273
+ if err != nil {
274
+ return fmt .Errorf ("failed to copy file from remote host to %s: %w" , dp , err )
275
+ }
276
+ }
277
+ return nil
144
278
}
145
279
146
280
func runTests (ctx context.Context , logger Logger , name string , prefix string , script string , sshClient SSHClient , tests []define.BatchPackageTests ) ([]OSRunnerPackageResult , error ) {
0 commit comments