Skip to content

Commit 78ed294

Browse files
committed
support /latest/ and others in build-details handler for consistency
1 parent 7dfb7f4 commit 78ed294

File tree

3 files changed

+106
-16
lines changed

3 files changed

+106
-16
lines changed

.sqlx/query-61e8789f7d2ddcfa951dc86c5f455cf4451f8f3b683c6bd1033e8ebaab97692e.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Justfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ sqlx-prepare ADDITIONAL_ARGS="":
1111
sqlx-check:
1212
just sqlx-prepare "--check"
1313

14-
lint:
15-
cargo clippy --all-features --all-targets --workspace --locked -- -D warnings
14+
lint *args:
15+
cargo clippy --all-features --all-targets --workspace --locked {{ args }} -- -D warnings
16+
17+
lint-fix:
18+
just lint --fix --allow-dirty --allow-staged
1619

1720
lint-js *args:
1821
deno run -A npm:eslint@9 static templates gui-tests eslint.config.js {{ args }}

src/web/build_details.rs

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ use crate::{
22
AsyncStorage, Config,
33
db::{
44
BuildId,
5-
types::{BuildStatus, version::Version},
5+
types::BuildStatus,
66
},
77
impl_axum_webpage,
88
web::{
99
MetaData,
10+
cache::CachePolicy,
1011
error::{AxumNope, AxumResult},
1112
extractors::{DbConnection, Path, rustdoc::RustdocParams},
1213
file::File,
13-
filters,
14+
filters, match_version,
1415
page::templates::{RenderBrands, RenderRegular, RenderSolid},
1516
},
1617
};
@@ -55,24 +56,37 @@ impl BuildDetailsPage {
5556

5657
#[derive(Clone, Deserialize, Debug)]
5758
pub(crate) struct BuildDetailsParams {
58-
pub(crate) name: String,
59-
pub(crate) version: Version,
6059
pub(crate) id: String,
6160
pub(crate) filename: Option<String>,
6261
}
6362

6463
pub(crate) async fn build_details_handler(
65-
Path(params): Path<BuildDetailsParams>,
64+
params: RustdocParams,
65+
Path(build_params): Path<BuildDetailsParams>,
6666
mut conn: DbConnection,
6767
Extension(config): Extension<Arc<Config>>,
6868
Extension(storage): Extension<Arc<AsyncStorage>>,
6969
) -> AxumResult<impl IntoResponse> {
70-
let id = params
70+
let id = build_params
7171
.id
7272
.parse()
7373
.map(BuildId)
7474
.map_err(|_| AxumNope::BuildNotFound)?;
7575

76+
let version = match_version(&mut conn, params.name(), params.req_version())
77+
.await?
78+
.assume_exact_name()?
79+
.into_canonical_req_version_or_else(|version| {
80+
AxumNope::Redirect(
81+
params
82+
.clone()
83+
.with_req_version(version)
84+
.build_details_url(id, build_params.filename.as_deref()),
85+
CachePolicy::ForeverInCdn,
86+
)
87+
})?
88+
.into_version();
89+
7690
let row = sqlx::query!(
7791
r#"SELECT
7892
builds.rustc_version,
@@ -87,8 +101,8 @@ pub(crate) async fn build_details_handler(
87101
INNER JOIN crates ON releases.crate_id = crates.id
88102
WHERE builds.id = $1 AND crates.name = $2 AND releases.version = $3"#,
89103
id.0,
90-
params.name,
91-
params.version.to_string(),
104+
params.name(),
105+
version as _
92106
)
93107
.fetch_optional(&mut *conn)
94108
.await?
@@ -114,7 +128,7 @@ pub(crate) async fn build_details_handler(
114128
.try_collect()
115129
.await?;
116130

117-
let current_filename = if let Some(filename) = params.filename {
131+
let current_filename = if let Some(filename) = build_params.filename {
118132
// if we have a given filename in the URL, we use that one.
119133
Some(filename)
120134
} else if let Some(default_target) = row.default_target {
@@ -144,8 +158,14 @@ pub(crate) async fn build_details_handler(
144158
(file_content, all_log_filenames, current_filename)
145159
};
146160

147-
let metadata = MetaData::from_crate(&mut conn, &params.name, &params.version, None).await?;
148-
let params = RustdocParams::from_metadata(&metadata);
161+
let metadata = MetaData::from_crate(
162+
&mut conn,
163+
params.name(),
164+
&version,
165+
Some(params.req_version().clone()),
166+
)
167+
.await?;
168+
let params = params.apply_metadata(&metadata);
149169

150170
Ok(BuildDetailsPage {
151171
metadata,
@@ -167,9 +187,12 @@ pub(crate) async fn build_details_handler(
167187

168188
#[cfg(test)]
169189
mod tests {
170-
use crate::test::{
171-
AxumResponseTestExt, AxumRouterTestExt, FakeBuild, async_wrapper,
172-
fake_release_that_failed_before_build,
190+
use crate::{
191+
db::types::{BuildId, ReleaseId},
192+
test::{
193+
AxumResponseTestExt, AxumRouterTestExt, FakeBuild, TestEnvironment, V0_1,
194+
async_wrapper, fake_release_that_failed_before_build,
195+
},
173196
};
174197
use kuchikiki::traits::TendrilSink;
175198
use test_case::test_case;
@@ -187,6 +210,22 @@ mod tests {
187210
.collect()
188211
}
189212

213+
async fn build_ids_for_release(
214+
conn: &mut sqlx::PgConnection,
215+
release_id: ReleaseId,
216+
) -> Vec<BuildId> {
217+
sqlx::query!(
218+
"SELECT id FROM builds WHERE rid = $1 ORDER BY id ASC",
219+
release_id as _
220+
)
221+
.fetch_all(conn)
222+
.await
223+
.unwrap()
224+
.into_iter()
225+
.map(|row| BuildId(row.id))
226+
.collect()
227+
}
228+
190229
#[test]
191230
fn test_partial_build_result() {
192231
async_wrapper(|env| async move {
@@ -475,4 +514,30 @@ mod tests {
475514
Ok(())
476515
});
477516
}
517+
518+
#[tokio::test(flavor = "multi_thread")]
519+
async fn build_detail_via_latest() -> anyhow::Result<()> {
520+
let env = TestEnvironment::new().await?;
521+
let rid = env
522+
.fake_release()
523+
.await
524+
.name("foo")
525+
.version(V0_1)
526+
.create()
527+
.await?;
528+
529+
let mut conn = env.async_db().async_conn().await;
530+
let build_id = {
531+
let ids = build_ids_for_release(&mut conn, rid).await;
532+
assert_eq!(ids.len(), 1);
533+
ids[0]
534+
};
535+
536+
env.web_app()
537+
.await
538+
.assert_success(&format!("/crate/foo/latest/builds/{build_id}"))
539+
.await?;
540+
541+
Ok(())
542+
}
478543
}

0 commit comments

Comments
 (0)