mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 15:12:02 +00:00
This PR ships our freshly rewritten container images built with rules_oci and Wolfi, which for now will only be used on S2. *What is this about* This work is the conjunction of [hardening container images](https://github.com/orgs/sourcegraph/projects/302?pane=issue&itemId=25019223) and fully building our container images with Bazel. * All base images are now distroless, based on Wolfi, meaning we fully control every little package version and we won't be subject anymore to Alpine maintainers dropping a postgres version for example. * Container images are now built with `rules_oci`, meaning we don't have Dockerfile anymore, but instead created through [Bazel rules](https://sourcegraph.sourcegraph.com/github.com/sourcegraph/sourcegraph@bzl/oci_wolfi/-/blob/enterprise/cmd/gitserver/BUILD.bazel). Don't be scared, while this will look a bit strange to you at first, it's much saner and simpler to do than our Dockerfiles and their muddy shell scripts calling themselves in cascade. :spiral_note_pad: *Plan*: *1/ (NOW) We merge our branch on `main` today, here is what it does change for you 👇:skin-tone-3::* * On `main`: * It will introduce a new job on `main` _Bazel Push_, which will push those new images on our registries with all tags prefixed by `bazel-`. * These new images will be picked up by S2 and S2 only. * The existing jobs building docker images and pushing them will stay in place until we have QA'ed them enough and are confident to roll them out on Dotcom. * Because we'll be building both images, there will be more jobs running on `main`, but this should not affect the wall clock time. * On all branches (so your PRs and `main`) * The _Bazel Test_ job will now run: Backend Integration Tests, E2E Tests and CodeIntel QA * This will increase the duration of your test jobs in PRs, but as we haven't removed yet the `sg lint` step, it should not affect too much the wall clock time of your PRs. * But it will also increase your confidence toward your changes, as the coverage will vastly increased compared to before. * If you have ongoing branches which are affecting the docker images (like adding a new binary, like the recent `scip-tags`, reach us out on #job-fair-bazel so we can help you to port your changes. It's much much simpler than before, but it's going to be unfamiliar to you). * If something goes awfully wrong, we'll rollback and update this thread. *2/ (EOW / Early next week) Once we're confident enough with what we saw on S2, we'll roll the new images on Dotcom.* * After the first successful deploy and a few sanity checks, we will drop the old images building jobs. * At this point, we'll reach out to all TLs asking for their help to exercise all features of our product to ensure we catch any potential breakage. ## Test plan <!-- All pull requests REQUIRE a test plan: https://docs.sourcegraph.com/dev/background-information/testing_principles --> * We tested our new images on `scale-testing` and it worked. * The new container building rules comes with _container tests_ which ensures that produced images are containing and configured with what should be in there: [example](https://sourcegraph.sourcegraph.com/github.com/sourcegraph/sourcegraph@bzl/oci_wolfi/-/blob/enterprise/cmd/gitserver/image_test.yaml) . --------- Co-authored-by: Dave Try <davetry@gmail.com> Co-authored-by: Will Dollman <will.dollman@sourcegraph.com>
151 lines
3.8 KiB
Go
151 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/sourcegraph/sourcegraph/dev/codeintel-qa/internal"
|
|
"github.com/sourcegraph/sourcegraph/lib/errors"
|
|
)
|
|
|
|
type uploadMeta struct {
|
|
id string
|
|
repoName string
|
|
commit string
|
|
}
|
|
|
|
// uploadAll uploads the dumps for the commits present in the given commitsByRepo map.
|
|
// Uploads are performed concurrently given the limiter instance as well as the set of
|
|
// flags supplied by the user. This function returns a slice of uploadMeta containing
|
|
// the graphql identifier of the uploaded resources.
|
|
func uploadAll(ctx context.Context, extensionAndCommitsByRepo map[string][]internal.ExtensionAndCommit, limiter *internal.Limiter) ([]uploadMeta, error) {
|
|
n := 0
|
|
for _, commits := range extensionAndCommitsByRepo {
|
|
n += len(commits)
|
|
}
|
|
|
|
var wg sync.WaitGroup
|
|
errCh := make(chan error, n)
|
|
uploadCh := make(chan uploadMeta, n)
|
|
|
|
for repoName, extensionAndCommits := range extensionAndCommitsByRepo {
|
|
for i, extensionAndCommit := range extensionAndCommits {
|
|
commit := extensionAndCommit.Commit
|
|
extension := extensionAndCommit.Extension
|
|
|
|
wg.Add(1)
|
|
|
|
go func(repoName, commit, file string) {
|
|
defer wg.Done()
|
|
|
|
if err := limiter.Acquire(ctx); err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
defer limiter.Release()
|
|
|
|
fmt.Printf("[%5s] %s Uploading index for %s@%s\n", internal.TimeSince(start), internal.EmojiLightbulb, repoName, commit[:7])
|
|
|
|
graphqlID, err := upload(ctx, internal.MakeTestRepoName(repoName), commit, file)
|
|
if err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
|
|
fmt.Printf("[%5s] %s Finished uploading index %s for %s@%s\n", internal.TimeSince(start), internal.EmojiSuccess, graphqlID, repoName, commit[:7])
|
|
|
|
uploadCh <- uploadMeta{
|
|
id: graphqlID,
|
|
repoName: repoName,
|
|
commit: commit,
|
|
}
|
|
}(repoName, commit, fmt.Sprintf("%s.%d.%s.%s", strings.Replace(repoName, "/", ".", 1), i, commit, extension))
|
|
}
|
|
}
|
|
|
|
go func() {
|
|
wg.Wait()
|
|
close(errCh)
|
|
close(uploadCh)
|
|
}()
|
|
|
|
for err := range errCh {
|
|
return nil, err
|
|
}
|
|
|
|
uploads := make([]uploadMeta, 0, n)
|
|
for upload := range uploadCh {
|
|
uploads = append(uploads, upload)
|
|
}
|
|
|
|
return uploads, nil
|
|
}
|
|
|
|
// upload invokes `src code-intel upload` on the host and returns the graphql identifier of
|
|
// the uploaded resource.
|
|
func upload(ctx context.Context, repoName, commit, file string) (string, error) {
|
|
argMap := map[string]string{
|
|
"root": "/",
|
|
"repo": repoName,
|
|
"commit": commit,
|
|
"file": file,
|
|
}
|
|
|
|
args := make([]string, 0, len(argMap))
|
|
for k, v := range argMap {
|
|
args = append(args, fmt.Sprintf("-%s=%s", k, v))
|
|
}
|
|
|
|
tempDir, err := os.MkdirTemp("", "codeintel-qa")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
src, err := os.Open(filepath.Join(indexDir, file))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer src.Close()
|
|
|
|
dst, err := os.OpenFile(filepath.Join(tempDir, file), os.O_CREATE|os.O_WRONLY, os.ModePerm)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if _, err := io.Copy(dst, src); err != nil {
|
|
_ = dst.Close()
|
|
return "", err
|
|
}
|
|
if err := dst.Close(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
cmd := exec.CommandContext(ctx, srcPath, append([]string{"lsif", "upload", "-json"}, args...)...)
|
|
cmd.Dir = tempDir
|
|
cmd.Env = os.Environ()
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("SRC_ENDPOINT=%s", internal.SourcegraphEndpoint))
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("SRC_ACCESS_TOKEN=%s", internal.SourcegraphAccessToken))
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return "", errors.Wrap(err, fmt.Sprintf("failed to upload index for %s@%s: %s", repoName, commit, output))
|
|
}
|
|
|
|
resp := struct {
|
|
UploadURL string `json:"uploadUrl"`
|
|
}{}
|
|
if err := json.Unmarshal(output, &resp); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
parts := strings.Split(resp.UploadURL, "/")
|
|
return parts[len(parts)-1], nil
|
|
}
|