Skip to content

Commit a136e92

Browse files
committed
Add script which wasn't commited by mistake. Notify about error only when 404 or 410 is returned to prevent false positives. Use Req instead of curl
1 parent 2ce3957 commit a136e92

2 files changed

Lines changed: 111 additions & 0 deletions

File tree

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ defmodule Membrane.PrecompiledDependencyProvider.MixProject do
7070
defp deps() do
7171
[
7272
{:bundlex, "~> 1.4"},
73+
{:req, "~> 0.5"},
7374
{:ex_doc, ">= 0.40.0", only: :dev, runtime: false},
7475
{:dialyxir, ">= 0.0.0", only: :dev, runtime: false},
7576
{:credo, ">= 0.0.0", only: :dev, runtime: false}

scripts/check_links.exs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Verifies that all URLs emitted by Membrane.PrecompiledDependencyProvider point to
2+
# existing artifacts. Run with: mix run scripts/check_links.exs
3+
4+
defmodule CheckLinks do
5+
@generic_dependencies [
6+
:dav1d,
7+
:"fdk-aac",
8+
:lame,
9+
:libnice,
10+
:libvpx,
11+
:mad,
12+
:opus,
13+
:portaudio,
14+
:sdl2,
15+
:srt,
16+
:srtp,
17+
:"svt-av1"
18+
]
19+
20+
@targets [
21+
%{architecture: "x86_64", os: "linux", abi: "gnu"},
22+
%{architecture: "aarch64", os: "linux", abi: "gnu"},
23+
%{architecture: "x86_64", os: "darwin22.6.0", abi: "gnu"},
24+
%{architecture: "aarch64", os: "darwin22.6.0", abi: "gnu"}
25+
]
26+
27+
# Artifacts that were never published; remove entries once they are.
28+
@known_broken [
29+
{:ffmpeg, "6.1.3", "x86_64", "darwin"},
30+
{:ffmpeg, "6.1.3", "aarch64", "darwin"},
31+
{:ffmpeg, "7.1.2", "x86_64", "darwin"},
32+
{:ffmpeg, "7.1.2", "aarch64", "darwin"},
33+
{:ffmpeg, "8.0", "x86_64", "darwin"}
34+
]
35+
36+
# No generic dependency publishes a macos_intel artifact.
37+
defp known_broken?(dep, _version, %{architecture: "x86_64", os: "darwin" <> _rest})
38+
when dep != :ffmpeg,
39+
do: true
40+
41+
defp known_broken?(dep, version, target) do
42+
{dep, version, target.architecture, os_family(target)} in @known_broken
43+
end
44+
45+
def run() do
46+
ffmpeg_cases =
47+
for version <- Membrane.PrecompiledDependencyProvider.known_ffmpeg_versions(),
48+
target <- @targets,
49+
do: {:ffmpeg, version, target}
50+
51+
generic_cases =
52+
for dep <- @generic_dependencies, target <- @targets, do: {dep, "latest", target}
53+
54+
cases =
55+
(ffmpeg_cases ++ generic_cases)
56+
|> Enum.reject(fn {dep, version, target} -> known_broken?(dep, version, target) end)
57+
58+
urls =
59+
cases
60+
|> Enum.map(fn {dep, version, target} ->
61+
Membrane.PrecompiledDependencyProvider.get_dependency_url(dep,
62+
version: version,
63+
target: target
64+
)
65+
end)
66+
|> Enum.reject(&is_nil/1)
67+
|> Enum.uniq()
68+
69+
IO.puts("Checking #{length(urls)} URLs...")
70+
71+
results =
72+
urls
73+
|> Task.async_stream(fn url -> {url, check(url)} end,
74+
max_concurrency: 10,
75+
timeout: 300_000
76+
)
77+
|> Enum.map(fn {:ok, result} -> result end)
78+
79+
# Only a confirmed 404/410 fails the job - transient errors (timeouts, 5xx etc.)
80+
# would create false-positive issues on CI.
81+
broken = for {url, :broken} <- results, do: url
82+
transient = for {url, {:transient, reason}} <- results, do: {url, reason}
83+
84+
Enum.each(transient, fn {url, reason} ->
85+
IO.puts("WARNING: could not verify (#{reason}): #{url}")
86+
end)
87+
88+
if broken == [] do
89+
IO.puts("No broken links found")
90+
else
91+
Enum.each(broken, &IO.puts("BROKEN: #{&1}"))
92+
System.halt(1)
93+
end
94+
end
95+
96+
# Req retries transient errors (timeouts, 5xx etc.) on its own before we classify.
97+
defp check(url) do
98+
case Req.head(url, receive_timeout: 30_000, redirect_log_level: false) do
99+
{:ok, %Req.Response{status: status}} when status in 200..399 -> :ok
100+
{:ok, %Req.Response{status: status}} when status in [404, 410] -> :broken
101+
{:ok, %Req.Response{status: status}} -> {:transient, status}
102+
{:error, error} -> {:transient, inspect(error)}
103+
end
104+
end
105+
106+
defp os_family(%{os: "darwin" <> _rest}), do: "darwin"
107+
defp os_family(%{os: os}), do: os
108+
end
109+
110+
CheckLinks.run()

0 commit comments

Comments
 (0)