-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests(e2e): collect and report PAM module coverage in e2e tests (#1032)
Add two new scripts, one that recompiles the PAM module to add coverage support, and one that collects the coverage at the end of the suite, before deprovisioning. For simplicity we only do these additional steps on a single runner, namely the Noble one. It's not worth it attempting to pool the coverage from all runners since it is most likely identical. The collected coverage is uploaded as an artifact on the workflow, with a deterministic name, so it can be easily downloaded and reused in the TICS check workflow. ------------------------- Another way of doing this, with less duplication in the workflows, would have been to download the E2E coverage in the QA workflow and combine it there. This would have given us the updated coverage in Codecov as well, with the side effect of adding more indirection because the coverage "journey" would become: ``` e2e workflow -> QA workflow -> TICS workflow ``` as opposed to ``` e2e workflow | -> TICS workflow QA workflow | ``` While it may make sense from a code duplication point of view (i.e. only use `reportgenerator` in the QA workflow and keep downloading a single coverage report in the TICS check), there's no functional argument for coupling the QA and e2e workflows like this, so I went with the more obvious approach. Fixes UDENG-3049
- Loading branch information
Showing
8 changed files
with
167 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Package main provides a script to recompile the adsys PAM module with coverage support. | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/ubuntu/adsys/e2e/internal/command" | ||
"github.com/ubuntu/adsys/e2e/internal/inventory" | ||
"github.com/ubuntu/adsys/e2e/internal/remote" | ||
"github.com/ubuntu/adsys/e2e/scripts" | ||
) | ||
|
||
var sshKey string | ||
|
||
func main() { | ||
os.Exit(run()) | ||
} | ||
|
||
func run() int { | ||
cmd := command.New(action, | ||
command.WithValidateFunc(validate), | ||
command.WithStateTransition(inventory.ADProvisioned, inventory.ADProvisioned), | ||
) | ||
cmd.Usage = fmt.Sprintf(`go run ./%s [options] | ||
Rebuild PAM module with coverage support with the goal of collecting coverage data at the end of the suite.`, filepath.Base(os.Args[0])) | ||
|
||
return cmd.Execute(context.Background()) | ||
} | ||
|
||
func validate(_ context.Context, cmd *command.Command) (err error) { | ||
sshKey, err = command.ValidateAndExpandPath(cmd.Inventory.SSHKeyPath, command.DefaultSSHKeyPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func action(ctx context.Context, cmd *command.Command) error { | ||
adsysRootDir, err := scripts.RootDir() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Establish remote connection | ||
client, err := remote.NewClient(cmd.Inventory.IP, "root", sshKey) | ||
if err != nil { | ||
return fmt.Errorf("failed to connect to VM: %w", err) | ||
} | ||
defer client.Close() | ||
|
||
// Install required dependencies to process coverage data | ||
if _, err := client.Run(ctx, "DEBIAN_FRONTEND=noninteractive apt-get install -y gcc gcovr libpam0g-dev"); err != nil { | ||
return fmt.Errorf("failed to install coverage dependencies: %w", err) | ||
} | ||
|
||
// Upload PAM module source code to a persistent location | ||
if err := client.Upload(filepath.Join(adsysRootDir, "pam", "pam_adsys.c"), "/root/pam/pam_adsys.c"); err != nil { | ||
return fmt.Errorf("failed to upload PAM module source code: %w", err) | ||
} | ||
|
||
// Rebuild PAM module in-place with coverage support | ||
if _, err := client.Run(ctx, fmt.Sprintf("gcc --coverage -shared -Wl,-soname,libpam_adsys.so -o %s/pam_adsys.so pam/pam_adsys.c -lpam", remote.PAMModuleDirectory)); err != nil { | ||
return fmt.Errorf("failed to compile PAM module: %w", err) | ||
} | ||
|
||
return nil | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Package main provides a script to collect PAM module coverage from the remote Ubuntu VM. | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/ubuntu/adsys/e2e/internal/command" | ||
"github.com/ubuntu/adsys/e2e/internal/inventory" | ||
"github.com/ubuntu/adsys/e2e/internal/remote" | ||
"github.com/ubuntu/adsys/e2e/scripts" | ||
) | ||
|
||
var sshKey string | ||
|
||
func main() { | ||
os.Exit(run()) | ||
} | ||
|
||
func run() int { | ||
cmd := command.New(action, | ||
command.WithValidateFunc(validate), | ||
command.WithStateTransition(inventory.ADProvisioned, inventory.ADProvisioned), | ||
) | ||
cmd.Usage = fmt.Sprintf(`go run ./%s [options] | ||
Collect PAM module coverage and save it locally to output/pam-cobertura.xml`, filepath.Base(os.Args[0])) | ||
|
||
return cmd.Execute(context.Background()) | ||
} | ||
|
||
func validate(_ context.Context, cmd *command.Command) (err error) { | ||
sshKey, err = command.ValidateAndExpandPath(cmd.Inventory.SSHKeyPath, command.DefaultSSHKeyPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func action(ctx context.Context, cmd *command.Command) error { | ||
adsysRootDir, err := scripts.RootDir() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Establish remote connection | ||
client, err := remote.NewClient(cmd.Inventory.IP, "root", sshKey) | ||
if err != nil { | ||
return fmt.Errorf("failed to connect to VM: %w", err) | ||
} | ||
defer client.Close() | ||
|
||
// Collect PAM module coverage if present | ||
if _, err := client.Run(ctx, fmt.Sprintf("gcovr --cobertura --output=/tmp/pam-cobertura.xml %s", remote.PAMModuleDirectory)); err != nil { | ||
return fmt.Errorf("failed to collect PAM module coverage: %w", err) | ||
} | ||
|
||
if err := client.Download("/tmp/pam-cobertura.xml", filepath.Join(adsysRootDir, "output", "pam-cobertura.xml")); err != nil { | ||
return fmt.Errorf("failed to download PAM module coverage: %w", err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters