Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,32 @@ For lists of builds see:

## Docker images

Docker images for Bob's Elixir and Erlang builds are built periodically. Bob checks for new Elixir and Erlang releases every 15 minutes and builds images for any new versions it discovers. The list of operating system distributions we base the images on can be found here: https://github.com/hexpm/bob/blob/main/lib/bob/job/docker_checker.ex#L5.
Docker images for Bob's Elixir and Erlang builds are built periodically. Bob checks for new Elixir and Erlang releases every 15 minutes and builds images for any new versions it discovers. The list of operating system distributions we base the images on is defined by `builds/0` in https://github.com/hexpm/bob/blob/main/lib/bob/job/docker_checker.ex.

Bob automatically builds the latest patch release of every version family: the newest release per Erlang `major.minor` line (for example only `26.2.5.21` out of the `26.2.x` line) and the newest Elixir patch release per minor version, for every compatible OTP major. Older patch versions are not built automatically but can be requested manually, see below.

Tagged images are never changed, that means `hexpm/erlang@22.0-alpine-3.11.2` will always target the tag `OTP-22.0` and won't update when `OTP-22.0.1` is released.

Erlang builds are found at https://hub.docker.com/r/hexpm/erlang, they use the versioning scheme `${OTP_VER}-${OS_NAME}-${OS_VER}` for tags. Builds for all releases since OTP 17 are provided.
Erlang builds are found at https://hub.docker.com/r/hexpm/erlang, they use the versioning scheme `${OTP_VER}-${OS_NAME}-${OS_VER}` for tags.

Elixir builds are found at https://hub.docker.com/r/hexpm/elixir, they use the versioning scheme `${ELIXIR_VER}-erlang-${OTP_VER}-${OS_NAME}-${OS_VER}`. Builds for all major releases since Elixir 1.0.0 are provided. Images are built for all pairs of compatible Elixir and OTP versions.
Elixir builds are found at https://hub.docker.com/r/hexpm/elixir, they use the versioning scheme `${ELIXIR_VER}-erlang-${OTP_VER}-${OS_NAME}-${OS_VER}`.

Builds are provided for the following OS and architectures using the docker `OS/ARCH` scheme:

* `linux/amd64`
* `linux/arm64/v8`

All provided images and tags can be searched at https://bob.hex.pm/docker.

### Examples of image names

* `hexpm/erlang:22.2.8-alpine-3.11.3`
* `hexpm/erlang:22.2-ubuntu-bionic-20200219`
* `hexpm/elixir:1.10.2-erlang-22.2.8-alpine-3.11.3`
* `hexpm/elixir:1.10.0-erlang-22.2-ubuntu-bionic-20200219`

### Requesting builds

If you need a specific patch version that is not built automatically, request it at https://bob.hex.pm/request. Sign in with your hex.pm account, then pick the image kind (Erlang or Elixir), the OS and base image version, and the exact Erlang (and Elixir) version. The image is built for both architectures, including the multi-arch manifest; when an Elixir image needs an Erlang base image that does not exist yet, the base is built first and the Elixir image follows automatically.

Requested builds are limited to ten image builds per user per hour. Build progress can be followed on the jobs dashboard at https://bob.hex.pm.
27 changes: 15 additions & 12 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ pre,
}

.flash {
margin: 10px auto 0;
max-width: 1240px;
margin: 0 0 18px;
border-radius: 8px;
background: var(--color-grey-800);
color: #fff;
padding: 8px 12px;
padding: 11px 14px;
font-size: 13px;
line-height: 1.35;
}

.bob {
Expand Down Expand Up @@ -126,14 +126,6 @@ pre,
letter-spacing: 0;
}

.bob-brand__tag {
color: var(--color-grey-400);
font-size: 12px;
font-weight: 500;
padding-left: 11px;
border-left: 1px solid var(--color-grey-700);
}

.bob-nav__tabs {
display: flex;
align-items: center;
Expand Down Expand Up @@ -287,6 +279,18 @@ pre,
color: var(--color-grey-400);
}

.nav-user {
color: var(--color-grey-300);
font-family: var(--font-mono);
font-size: 12.5px;
}

.req-intro {
padding: 14px 20px 0;
font-size: 13.5px;
color: var(--color-grey-600);
}

.bob-main {
flex: 1;
}
Expand Down Expand Up @@ -1079,7 +1083,6 @@ pre,
}

@media (max-width: 820px) {
.bob-brand__tag,
.nav-ext {
display: none;
}
Expand Down
3 changes: 2 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ config :bob,
master?: true,
parallel_jobs: 1,
local_jobs: [],
remote_jobs: []
remote_jobs: [],
hexpm_impl: Bob.Hexpm.Impl

config :mime, :types, %{
"application/vnd.bob+erlang" => ["erlang"]
Expand Down
5 changes: 4 additions & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import Config

config :bob,
master_schedule: [],
agent_schedule: []
agent_schedule: [],
hexpm_url: "http://localhost:4000",
oauth_client_id: "b0b00000-0000-4000-8000-000000000b0b",
oauth_client_secret: "dev_secret_for_testing"

config :bob, Bob.Repo,
username: "postgres",
Expand Down
5 changes: 4 additions & 1 deletion config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ if config_env() == :prod do
master?: System.fetch_env!("BOB_WHO") == "master",
parallel_jobs: String.to_integer(System.fetch_env!("BOB_PARALLEL_JOBS")),
local_jobs: jobs_fun.("BOB_LOCAL_JOBS"),
remote_jobs: jobs_fun.("BOB_REMOTE_JOBS")
remote_jobs: jobs_fun.("BOB_REMOTE_JOBS"),
hexpm_url: System.get_env("BOB_HEXPM_URL", "https://hex.pm"),
oauth_client_id: System.fetch_env!("BOB_OAUTH_CLIENT_ID"),
oauth_client_secret: System.fetch_env!("BOB_OAUTH_CLIENT_SECRET")

config :ex_aws,
access_key_id: System.fetch_env!("BOB_S3_ACCESS_KEY"),
Expand Down
7 changes: 6 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import Config

config :bob,
master_schedule: [],
agent_schedule: []
agent_schedule: [],
github: Bob.FakeGitHub,
hexpm_impl: Bob.FakeHexpm,
hexpm_url: "http://localhost:4000",
oauth_client_id: "b0b00000-0000-4000-8000-000000000b0b",
oauth_client_secret: "test_secret"

config :ex_aws,
access_key_id: "test",
Expand Down
1 change: 1 addition & 0 deletions lib/bob/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule Bob.Application do
{Finch, name: Bob.Finch},
{Task.Supervisor, [name: Bob.Tasks]},
{Phoenix.PubSub, name: Bob.PubSub},
Bob.Cache,
Bob.DockerHub.RateLimiter,
Bob.DockerHub.Auth,
runner_spec(),
Expand Down
42 changes: 37 additions & 5 deletions lib/bob/artifacts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,19 @@ defmodule Bob.Artifacts do
|> MapSet.new()
end

@doc """
The architectures a single tag covers, or `nil` if the tag is absent. Used to
tell whether a manifest tag already spans every architecture.
"""
def docker_tag_archs(repo, tag) do
Repo.one(
from(d in DockerTag,
where: d.repo == ^repo and d.tag == ^tag,
select: d.archs
)
)
end

@doc """
`{repo, tag}` for every tag of `repos` whose search metadata carries one of
`os_versions`. Scopes the checker's erlang reads to current base images —
Expand Down Expand Up @@ -471,18 +484,37 @@ defmodule Bob.Artifacts do

def replace_base_image_tags(repo, tags) do
now = DateTime.utc_now()
tags = Enum.uniq(tags)
rows = Enum.map(tags, &%{repo: repo, tag: &1, inserted_at: now, updated_at: now})

rows =
tags |> Enum.uniq() |> Enum.map(&%{repo: repo, tag: &1, inserted_at: now, updated_at: now})

# Prune vanished tags but keep existing rows untouched, so inserted_at marks
# when a base image first appeared rather than the last reconcile.
Repo.transaction(fn ->
Repo.delete_all(from(b in BaseImageTag, where: b.repo == ^repo))
Repo.insert_all(BaseImageTag, rows)
Repo.delete_all(from(b in BaseImageTag, where: b.repo == ^repo and b.tag not in ^tags))
Repo.insert_all(BaseImageTag, rows, on_conflict: :nothing, conflict_target: [:repo, :tag])
end)

:ok
end

@doc """
`{os, tag}` for every base image first seen on or after `cutoff`. A recent
base image is one of the components that makes a build worth triggering.
"""
def recent_base_image_versions(cutoff) do
Repo.all(
from(b in BaseImageTag,
where: b.inserted_at >= ^cutoff,
select: {b.repo, b.tag}
)
)
|> Enum.flat_map(fn
{"library/" <> os, tag} -> [{os, tag}]
_other -> []
end)
|> MapSet.new()
end

def upsert(attrs) do
%Artifact{}
|> Artifact.changeset(attrs)
Expand Down
Loading
Loading