Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a7f3b21
Add scripts to prepare distributions
jsoriano May 16, 2025
6e0af0f
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Jul 5, 2025
e70a21c
Run actions in parallel
jsoriano Jul 5, 2025
10118ea
Select lite packages per version
jsoriano Jul 5, 2025
b31b25e
Add 8.19 and 9.1
jsoriano Jul 5, 2025
0b47e15
linting
jsoriano Jul 7, 2025
d93fdf9
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Aug 5, 2025
10b90f5
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Nov 14, 2025
9cc14d4
Support pinned package versions
jsoriano Nov 14, 2025
a967daa
Reuse existing packages
jsoriano Nov 15, 2025
8aa3e5b
Add Dockerfile
jsoriano Nov 15, 2025
1148a75
Add sample for pinned versions
jsoriano Nov 16, 2025
3ac5e33
Use ProtonMail fork of opengpg
jsoriano Nov 17, 2025
e6ca112
Use github.com/Masterminds/semver/v3
jsoriano Nov 17, 2025
973d306
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Jan 20, 2026
ce4573e
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Jan 23, 2026
468598f
Remove unused dockerfile
jsoriano Feb 9, 2026
ff94b0d
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Feb 9, 2026
5ecac86
Apply comments from review
jsoriano Feb 10, 2026
dcc6d5e
Add tests, fix race condition
jsoriano Feb 10, 2026
a4bc751
Fix tests
jsoriano Feb 10, 2026
35463c9
Move cmd/distribution to its own module
jsoriano Feb 10, 2026
135ac07
Merge remote-tracking branch 'origin/main' into cmd-distribution-scripts
jsoriano Feb 10, 2026
edcd868
Update AGENTS.md with recommendations about the use of require and as…
jsoriano Feb 10, 2026
e9ee6c9
Update magefile
jsoriano Feb 10, 2026
002720e
Remove too specific readme section
jsoriano Feb 10, 2026
27ae7af
Address some small issues
jsoriano Feb 10, 2026
e628e53
Fix test names
jsoriano Feb 10, 2026
787984d
Apply suggestions from review
jsoriano Feb 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions cmd/distribution/GPG-KEY-elasticsearch
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD
A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9
CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ
j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd
1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD
2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg
KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy
Y2gub3JnPokBTgQTAQgAOAIbAwIXgBYhBEYJWsyFSFgsGiaZqdJ9ZmzYjkK0BQJk
9vrZBQsJCAcDBRUKCQgLBRYCAwEAAh4FAAoJENJ9ZmzYjkK00hoH+wYXZKgVb3Wv
4AA/+T1IAf7edwgajr58bEyqds6/4v6uZBneUaqahUqMXgLFRX5dBSrAS7bvE/jx
+BBQx+rpFGxSwvFegRevE1zAGVtpgkFQX0RpRcKSmksucSBxikR/dPn9XdJSEVa8
vPcs11V+2E5tq3LEP14zJL4MkJKQF0VJl5UUmKLS7U2F/IB5aXry9UWdMTnwNntX
kl2iDaViYF4MC6xTS24uLwND2St0Jvjt+xGEwbdBVvp+UZ/kG6IGkYM5eWGPuok/
DHvjUdwTfyO9b5xGbqn5FJ3UFOwB/nOSFXHM8rsHRT/67gHcIl8YFqSQXpIkk9D3
dCY+KieW0ue5AQ0EUjceygEIAOSVJc3DFuf3LsmUfGpUmnCqoUm76Eqqm8xynFEG
ZpczTChkwARRtckcfa/sGv376j+jk0c0Q71Uv3MnMLPGF+w3bpu8fLiPeW/cntf1
8uZ6DxJvHA/oaZZ6VPjwUGSeVydiPtZfTYsceO8Dxl3gpS6nHZ9Gsnfr/kcH9/11
Ca73HBtmGVIkOI1mZKMbANO8cewY/i7fPxShu7B0Rb3jxVNGUuiRcfRiao0gWx0U
ZGpvuHplt7loFX2cbsHFAp9WsjYEbSohb/Y0K4NkyFhL82MfbcsEwsXPhRTFgJWw
s4vpuFg/kFFlnw0NNPVP1jNJLNCsMBMEpP1A7k6MRpylNnUAEQEAAYkBNgQYAQgA
IAIbDBYhBEYJWsyFSFgsGiaZqdJ9ZmzYjkK0BQJk9vsHAAoJENJ9ZmzYjkK0hWsH
/ArKtn12HM3+41zYo9qO4rTri7+IYTjSB/JDTOusZgZLd/HCp1xQo4SI2Eur3Rtx
USMWK1LEeBzsjwDT9yVceYekrBEqUVyRMSVYj+UeZK2s4LbXm9b4jxXVtaivmkMA
jtznndrD7kmm8ak+UsZplf6p6uZS9TZ9hjwoMmw5oMaS6TZkLT4KYGWeyzHJSUBX
YikY6vssDQu4SJ07m1f4Hz81J39QOcHln5I5HTK8Rh/VUFcxNnGg9360g55wWpiF
eUTeMyoXpOtffiUhiOtbRYsmSYC0D4Fd5yJnO3n1pwnVVVsM7RAC22rc5j/Dw8dR
GIHikRcYWeXTYW7veewK5Ss=
=ftS0
-----END PGP PUBLIC KEY BLOCK-----
1 change: 1 addition & 0 deletions cmd/distribution/Makefile

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need a copy of Makefile from root here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To have the same release targets, though I could remove it as this is not used by now...

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../../Makefile
6 changes: 6 additions & 0 deletions cmd/distribution/all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Base address of the Package Registry
address: "https://epr.elastic.co"

queries:
- all: true
prerelease: true
68 changes: 68 additions & 0 deletions cmd/distribution/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License 2.0;
// you may not use this file except in compliance with the Elastic License 2.0.

package main

import "fmt"

func Example_config_urls() {
config := config{
Address: "http://localhost:8080",
Queries: []configQuery{
{},
{Prerelease: true},
{KibanaVersion: "7.19.0"},
{KibanaVersion: "7.19.0", Prerelease: true},
{SpecMin: "2.3", SpecMax: "3.0"},
},
}

urls, err := config.searchURLs()
if err != nil {
panic(err)
}

for u := range urls {
fmt.Println(u)
}

// Output:
// http://localhost:8080/search
// http://localhost:8080/search?prerelease=true
// http://localhost:8080/search?kibana.version=7.19.0
// http://localhost:8080/search?kibana.version=7.19.0&prerelease=true
// http://localhost:8080/search?spec.max=3.0&spec.min=2.3
}

func Example_config_urls_matrix() {
config := config{
Address: "http://localhost:8080",
Matrix: []configQuery{
{},
{Prerelease: true},
},
Queries: []configQuery{
{},
{KibanaVersion: "7.19.0"},
{SpecMin: "2.3", SpecMax: "3.0"},
},
}

urls, err := config.searchURLs()
if err != nil {
panic(err)
}

for u := range urls {
fmt.Println(u)
}

// Output:
// http://localhost:8080/search
// http://localhost:8080/search?kibana.version=7.19.0
// http://localhost:8080/search?spec.max=3.0&spec.min=2.3
// http://localhost:8080/search?prerelease=true
// http://localhost:8080/search?kibana.version=7.19.0&prerelease=true
// http://localhost:8080/search?prerelease=true&spec.max=3.0&spec.min=2.3
}
110 changes: 110 additions & 0 deletions cmd/distribution/download.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License 2.0;
// you may not use this file except in compliance with the Elastic License 2.0.

package main

import (
"bytes"
_ "embed"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path"
"path/filepath"

"github.com/ProtonMail/go-crypto/openpgp"
Comment thread
mrodm marked this conversation as resolved.
)

type downloadAction struct {
client *http.Client
keyRing openpgp.KeyRing

Address string `yaml:"address"`
Destination string `yaml:"destination"`
}

// publicKey is the public key of the key used to sign elastic artifacts.
// Downloaded from https://artifacts.elastic.co/GPG-KEY-elasticsearch
//
//go:embed GPG-KEY-elasticsearch
var publicKey []byte

func (a *downloadAction) init(c config) error {
a.client = &http.Client{}
if a.Address == "" {
a.Address = c.Address
}
err := os.MkdirAll(a.Destination, 0755)
if err != nil {
return fmt.Errorf("failed to create desination directory: %w", err)
}
a.keyRing, err = openpgp.ReadArmoredKeyRing(bytes.NewReader(publicKey))
if err != nil {
return fmt.Errorf("failed to initialize public key: %w", err)
}
return nil
}

func (a *downloadAction) perform(i packageInfo) error {
if valid, _ := a.valid(i); valid {
return nil
}
if err := a.download(i.Download); err != nil {
return fmt.Errorf("failed to download package %s: %w", i.Download, err)
}
if err := a.download(i.SignaturePath); err != nil {
return fmt.Errorf("failed to download signature %s: %w", i.SignaturePath, err)
}
return nil
}

func (a *downloadAction) download(urlPath string) error {
p, err := url.JoinPath(a.Address, urlPath)
if err != nil {
return fmt.Errorf("failed to build url: %w", err)
}
resp, err := a.client.Get(p)
if err != nil {
return fmt.Errorf("failed to get %s: %w", urlPath, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to get %s (status code %d)", urlPath, resp.StatusCode)
}

f, err := os.Create(a.destinationPath(urlPath))
if err != nil {
return fmt.Errorf("failed to open %s in %s: %w", path.Base(urlPath), a.Destination, err)
}
defer f.Close()

_, err = io.Copy(f, resp.Body)
return err
}

func (a *downloadAction) destinationPath(urlPath string) string {
return filepath.Join(a.Destination, path.Base(urlPath))
}

func (a *downloadAction) valid(info packageInfo) (bool, error) {
signed, err := os.Open(a.destinationPath(info.Download))
if err != nil {
return false, err
}
defer signed.Close()

signature, err := os.Open(a.destinationPath(info.SignaturePath))
if err != nil {
return false, err
}
defer signature.Close()

_, err = openpgp.CheckArmoredDetachedSignature(a.keyRing, signed, signature, nil)
if err != nil {
return false, err
}
return true, nil
}
90 changes: 90 additions & 0 deletions cmd/distribution/lite.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Base address of the Package Registry
address: "https://epr.elastic.co"

# Queries are executed with each one of the parameters of the matrix.
matrix:
- kibana.version: 7.17.26
- kibana.version: 7.17.27
- kibana.version: 7.17.28
- kibana.version: 7.17.29
- kibana.version: 8.15.4
- kibana.version: 8.15.5
- kibana.version: 8.15.6
- kibana.version: 8.16.0
spec.max: 3.3
- kibana.version: 8.16.1
spec.max: 3.3
- kibana.version: 8.16.2
spec.max: 3.3
- kibana.version: 8.16.3
spec.max: 3.3
- kibana.version: 8.16.4
spec.max: 3.3
- kibana.version: 8.16.5
spec.max: 3.3
- kibana.version: 8.16.6
spec.max: 3.3
- kibana.version: 8.16.7
spec.max: 3.3
- kibana.version: 8.17.0
spec.max: 3.3
- kibana.version: 8.17.1
spec.max: 3.3
- kibana.version: 8.17.2
spec.max: 3.3
- kibana.version: 8.17.3
spec.max: 3.3
- kibana.version: 8.17.4
spec.max: 3.3
- kibana.version: 8.17.5
spec.max: 3.3
- kibana.version: 8.17.6
spec.max: 3.3
- kibana.version: 8.17.7
spec.max: 3.3
- kibana.version: 8.18.0
spec.max: 3.3
- kibana.version: 8.18.1
spec.max: 3.3
- kibana.version: 8.18.2
spec.max: 3.3
- kibana.version: 8.19.0
spec.max: 3.4
- kibana.version: 9.0.0
spec.min: 2.3
spec.max: 3.3
- kibana.version: 9.0.1
spec.min: 2.3
spec.max: 3.3
- kibana.version: 9.0.2
spec.min: 2.3
spec.max: 3.3
- kibana.version: 9.1.0
spec.min: 2.3
spec.max: 3.4
- spec.min: 2.3
spec.max: 3.4

# Queries to execute to discover packages.
queries:
- package: apache
- package: apm
- package: elastic_agent
- package: endpoint
- package: fleet_server
- package: linux
- package: log
- package: mysql
- package: nginx
- package: profiler_collector
- package: profiler_symbolizer
- package: security_ai_prompts
- package: security_detection_engine
- package: synthetics
- package: system
- package: windows

actions:
- print:
- download:
destination: ./build/distribution-lite
Loading