diff --git a/.dockerignore b/.dockerignore index ea4a0ace1..4c9a2b70c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ /.rustwide +/ignored **/target diff --git a/.env.sample b/.env.sample new file mode 100644 index 000000000..383a7db4b --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +CRATESFYI_GITHUB_USERNAME= +CRATESFYI_GITHUB_ACCESSTOKEN= diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 863289c23..76b5209a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,3 +21,25 @@ jobs: - name: Test docs.rs run: cargo test -- --test-threads=1 + + docker: + name: Docker + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@master + with: + fetch-depth: 2 + + - name: Build the Docker image + run: docker build -t docsrs . + + - name: Upload the Docker image to ECR + uses: rust-lang/simpleinfra/github-actions/upload-docker-image@master + with: + image: docsrs + repository: docsrs + region: us-west-1 + aws_access_key_id: "${{ secrets.aws_access_key_id }}" + aws_secret_access_key: "${{ secrets.aws_secret_access_key }}" + if: github.ref == 'refs/heads/master' diff --git a/.gitignore b/.gitignore index e5e7c1e51..9724e40b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +/ignored +/.env target *.css *.css.map diff --git a/Dockerfile b/Dockerfile index ab213ebe8..f0a567742 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,58 +1,74 @@ -FROM rust:slim +# To produce a smaller image this Dockerfile contains two separate stages: in +# the first one all the build dependencies are installed and docs.rs is built, +# while in the second one just the runtime dependencies are installed, with the +# binary built in the previous stage copied there. +# +# As of 2019-10-29 this reduces the image from 2.8GB to 500 MB. -### STEP 1: Install dependencies ### -# Install packaged dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential git curl cmake gcc g++ pkg-config libmagic-dev \ - libssl-dev zlib1g-dev sudo docker.io +################# +# Build stage # +################# -### STEP 2: Create user ### -ENV HOME=/home/cratesfyi -RUN adduser --home $HOME --disabled-login --disabled-password --gecos "" cratesfyi +FROM ubuntu:bionic AS build -### STEP 3: Setup build environment as new user ### -ENV CRATESFYI_PREFIX=/home/cratesfyi/prefix -RUN mkdir $CRATESFYI_PREFIX && chown cratesfyi:cratesfyi "$CRATESFYI_PREFIX" +# Install packaged dependencies +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential git curl cmake gcc g++ pkg-config libmagic-dev \ + libssl-dev zlib1g-dev ca-certificates -USER cratesfyi -RUN mkdir -vp "$CRATESFYI_PREFIX"/documentations "$CRATESFYI_PREFIX"/public_html "$CRATESFYI_PREFIX"/sources -RUN git clone https://github.com/rust-lang/crates.io-index.git "$CRATESFYI_PREFIX"/crates.io-index -RUN git --git-dir="$CRATESFYI_PREFIX"/crates.io-index/.git branch crates-index-diff_last-seen +# Install the stable toolchain with rustup +RUN curl https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init >/tmp/rustup-init && \ + chmod +x /tmp/rustup-init && \ + /tmp/rustup-init -y --no-modify-path --default-toolchain stable --profile minimal +ENV PATH=/root/.cargo/bin:$PATH -### STEP 4: Build the project ### # Build the dependencies in a separate step to avoid rebuilding all of them # every time the source code changes. This takes advantage of Docker's layer # caching, and it works by copying the Cargo.{toml,lock} with dummy source code # and doing a full build with it. -RUN mkdir -p ~/docs.rs ~/docs.rs/src/web/badge -WORKDIR $HOME/docs.rs -COPY --chown=cratesfyi Cargo.lock Cargo.toml ./ -COPY --chown=cratesfyi src/web/badge src/web/badge/ +RUN mkdir -p /build/src/web/badge +WORKDIR /build +COPY Cargo.lock Cargo.toml ./ +COPY src/web/badge src/web/badge/ RUN echo "fn main() {}" > src/main.rs && \ echo "fn main() {}" > build.rs RUN cargo fetch RUN cargo build --release -### STEP 5: Build the website ### # Dependencies are now cached, copy the actual source code and do another full # build. The touch on all the .rs files is needed, otherwise cargo assumes the # source code didn't change thanks to mtime weirdness. RUN rm -rf src build.rs -COPY --chown=cratesfyi build.rs build.rs +COPY .git .git +COPY build.rs build.rs RUN touch build.rs -COPY --chown=cratesfyi src src/ +COPY src src/ RUN find src -name "*.rs" -exec touch {} \; -COPY --chown=cratesfyi templates/style.scss templates/ +COPY templates/style.scss templates/ RUN cargo build --release -ADD templates templates/ -ADD css $CRATESFYI_PREFIX/public_html +################## +# Output stage # +################## + +FROM ubuntu:bionic AS output + +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ + git \ + libmagic1 \ + docker.io \ + ca-certificates + +RUN mkdir -p /opt/docsrs/prefix + +COPY --from=build /build/target/release/cratesfyi /usr/local/bin +COPY css /opt/docsrs/prefix/public_html +COPY templates /opt/docsrs/templates +COPY docker-entrypoint.sh /opt/docsrs/entrypoint.sh -ENV DOCS_RS_DOCKER=true -COPY docker-entrypoint.sh ./ -USER root -ENTRYPOINT ["./docker-entrypoint.sh"] +WORKDIR /opt/docsrs +ENTRYPOINT ["/opt/docsrs/entrypoint.sh"] CMD ["daemon", "--foreground"] diff --git a/README.md b/README.md index e5c2407bc..a228b7304 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,14 @@ Make sure you have docker-compose and are able to download ~10GB data on the fir ```sh git clone https://github.com/rust-lang/docs.rs.git docs.rs cd docs.rs +cp .env.sample .env docker-compose up # This may take a half hour or more on the first run ``` +If you need to store big files in the repository's directory it's recommended to +put them in the `ignored/` subdirectory, which is ignored both by git and +Docker. + ### CLI #### Starting web server diff --git a/css/main-20160526-1.10.0-nightly-97e3a2401.css b/css/main-20160526-1.10.0-nightly-97e3a2401.css new file mode 100644 index 000000000..59b2ff7e3 --- /dev/null +++ b/css/main-20160526-1.10.0-nightly-97e3a2401.css @@ -0,0 +1,128 @@ +/** + * Copyright 2015 The Rust Project Developers. See the COPYRIGHT + * file at the top-level directory of this distribution and at + * http://rust-lang.org/COPYRIGHT. + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +/* General structure and fonts */ + +body { + background-color: white; + color: black; +} + +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { + color: black; +} +h1.fqn { + border-bottom-color: #D5D5D5; +} +h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { + border-bottom-color: #DDDDDD; +} +.in-band, code { + background-color: white; +} + +.docblock code { + background-color: #F5F5F5; +} +pre { + background-color: #F5F5F5; +} + +.sidebar .location { + background: #e1e1e1; + color: #333; +} + +.block a:hover { + background: #F5F5F5; +} + +.line-numbers span { color: #c67e2d; } +.line-numbers .line-highlighted { + background-color: #f6fdb0 !important; +} + +:target { background: #FDFFD3; } +.content .highlighted { + color: #000 !important; + background-color: #ccc; +} +.content .highlighted a, .content .highlighted span { color: #000 !important; } +.content .highlighted.trait { background-color: #fece7e; } +.content .highlighted.mod { background-color: #afc6e4; } +.content .highlighted.enum { background-color: #b4d1b9; } +.content .highlighted.struct { background-color: #e7b1a0; } +.content .highlighted.fn { background-color: #c6afb3; } +.content .highlighted.method { background-color: #c6afb3; } +.content .highlighted.tymethod { background-color: #c6afb3; } +.content .highlighted.type { background-color: #c6afb3; } + +.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { + border-bottom-color: #DDD; +} + +.docblock table { + border-color: #ddd; +} + +.docblock table td { + border-top-color: #ddd; + border-bottom-color: #ddd; +} + +.docblock table th { + border-top-color: #ddd; + border-bottom-color: #ddd; +} + +.content a.primitive { color: #39a7bf; } +.content span.externcrate, span.mod, .content a.mod, block a.current.mod { color: #4d76ae; } +.content span.fn, .content a.fn, .block a.current.fn, +.content span.method, .content a.method, .block a.current.method, +.content span.tymethod, .content a.tymethod, .block a.current.tymethod, +.content .fnname { color: #8c6067; } + +pre.rust .comment { color: #8E908C; } +pre.rust .doccomment { color: #4D4D4C; } + +nav { + border-bottom-color: #e0e0e0; +} +nav.main .current { + border-top-color: #000; + border-bottom-color: #000; +} +nav.main .separator { + border-color: 1px solid #000; +} +a { + color: #000; +} + +.docblock a, .stability a { + color: #3873AD; +} + +a.test-arrow { + color: #f5f5f5; +} + +.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; } + +.search-input { + color: #555; + box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent; + background-color: white; +} + +em.stab.unstable { background: #FFF5D6; border-color: #FFC600; } +em.stab.deprecated { background: #F3DFFF; border-color: #7F0087; } diff --git a/css/rustdoc-20160526-1.10.0-nightly-97e3a2401.css b/css/rustdoc-20160526-1.10.0-nightly-97e3a2401.css new file mode 100644 index 000000000..8e4245d4e --- /dev/null +++ b/css/rustdoc-20160526-1.10.0-nightly-97e3a2401.css @@ -0,0 +1,717 @@ +/** + * Copyright 2013 The Rust Project Developers. See the COPYRIGHT + * file at the top-level directory of this distribution and at + * http://rust-lang.org/COPYRIGHT. + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +/* See FiraSans-LICENSE.txt for the Fira Sans license. */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 400; + src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); +} +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 500; + src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); +} + +/* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license and + * Heuristica-LICENSE.txt for the Heuristica license. */ +@font-face { + font-family: 'Source Serif Pro'; + font-style: normal; + font-weight: 400; + src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff'); +} +@font-face { + font-family: 'Source Serif Pro'; + font-style: italic; + font-weight: 400; + src: url("Heuristica-Italic.woff") format('woff'); +} +@font-face { + font-family: 'Source Serif Pro'; + font-style: normal; + font-weight: 700; + src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff'); +} + +/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff'); +} +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 600; + src: local('Source Code Pro Semibold'), url("SourceCodePro-Semibold.woff") format('woff'); +} + +@import "normalize.css"; + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* General structure and fonts */ + +body { + font: 16px/1.4 "Source Serif Pro", Georgia, Times, "Times New Roman", serif; + margin: 0; + position: relative; + padding: 10px 15px 20px 15px; + + -webkit-font-feature-settings: "kern", "liga"; + -moz-font-feature-settings: "kern", "liga"; + font-feature-settings: "kern", "liga"; +} + +h1 { + font-size: 1.5em; +} +h2 { + font-size: 1.4em; +} +h3 { + font-size: 1.3em; +} +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { + font-weight: 500; + margin: 20px 0 15px 0; + padding-bottom: 6px; +} +h1.fqn { + border-bottom: 1px dashed; + margin-top: 0; + position: relative; +} +h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { + border-bottom: 1px solid; +} +h3.impl, h3.method, h4.method, h3.type, h4.type { + font-weight: 600; + margin-top: 10px; + margin-bottom: 10px; + position: relative; +} +h3.impl, h3.method, h3.type { + margin-top: 15px; +} +h1, h2, h3, h4, .sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle { + font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +ol, ul { + padding-left: 25px; +} +ul ul, ol ul, ul ol, ol ol { + margin-bottom: 0; +} + +p { + margin: 0 0 .6em 0; +} + +code, pre { + font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace; + white-space: pre-wrap; +} +.docblock code { + border-radius: 3px; + padding: 0 0.2em; +} +.docblock pre code { + padding: 0; +} +pre { + padding: 14px; +} + +.source pre { + padding: 20px; +} + +img { + max-width: 100%; +} + +.content.source { + margin-top: 50px; + max-width: none; + overflow: visible; + margin-left: 0px; + min-width: 70em; +} + +nav.sub { + font-size: 16px; + text-transform: uppercase; +} + +.sidebar { + width: 200px; + position: absolute; + left: 0; + top: 0; + min-height: 100%; +} + +.content, nav { max-width: 960px; } + +/* Everything else */ + +.js-only, .hidden { display: none !important; } + +.sidebar { + padding: 10px; +} +.sidebar img { + margin: 20px auto; + display: block; +} + +.sidebar .location { + font-size: 17px; + margin: 30px 0 20px 0; + text-align: center; +} + +.location a:first-child { font-weight: 500; } + +.block { + padding: 0 10px; + margin-bottom: 14px; +} +.block h2, .block h3 { + margin-top: 0; + margin-bottom: 8px; + text-align: center; +} +.block ul, .block li { + margin: 0; + padding: 0; + list-style: none; +} + +.block a { + display: block; + text-overflow: ellipsis; + overflow: hidden; + line-height: 15px; + padding: 7px 5px; + font-size: 14px; + font-weight: 300; + transition: border 500ms ease-out; +} + +.content { + padding: 15px 0; +} + +.content.source pre.rust { + white-space: pre; + overflow: auto; + padding-left: 0; +} +.content pre.line-numbers { + float: left; + border: none; + position: relative; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.line-numbers span { cursor: pointer; } + +.docblock.short p { + display: inline; +} + +.docblock.short.nowrap { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.docblock.short p { + overflow: hidden; + text-overflow: ellipsis; + margin: 0; +} +.docblock.short code { white-space: nowrap; } + +.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { + border-bottom: 1px solid; +} + +.docblock h1 { font-size: 1.3em; } +.docblock h2 { font-size: 1.15em; } +.docblock h3, .docblock h4, .docblock h5 { font-size: 1em; } + +.content .out-of-band { + font-size: 23px; + margin: 0px; + padding: 0px; + text-align: right; + display: inline-block; + font-weight: normal; + position: absolute; + right: 0; +} + +h3.impl > .out-of-band { + font-size: 21px; +} + +h4 > code, h3 > code { + position: inherit; +} + +.in-band, code { + z-index: 5; +} + +.content .in-band { + margin: 0px; + padding: 0px; + display: inline-block; +} + +#main { position: relative; } +#main > .since { + top: inherit; + font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.content table { + border-spacing: 0 5px; + border-collapse: separate; +} +.content td { vertical-align: top; } +.content td:first-child { padding-right: 20px; } +.content td p:first-child { margin-top: 0; } +.content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; } + +.docblock table { + border: 1px solid; + margin: .5em 0; + border-collapse: collapse; + width: 100%; +} + +.docblock table td { + padding: .5em; + border-top: 1px dashed; + border-bottom: 1px dashed; +} + +.docblock table th { + padding: .5em; + text-align: left; + border-top: 1px solid; + border-bottom: 1px solid; +} + +.content .item-list { + list-style-type: none; + padding: 0; +} + +.content .item-list li { margin-bottom: 3px; } + +.content .multi-column { + -moz-column-count: 5; + -moz-column-gap: 2.5em; + -webkit-column-count: 5; + -webkit-column-gap: 2.5em; + column-count: 5; + column-gap: 2.5em; +} +.content .multi-column li { width: 100%; display: inline-block; } + +.content .method { + font-size: 1em; + position: relative; +} +/* Shift "where ..." part of method or fn definition down a line */ +.content .method .where, .content .fn .where { display: block; } +/* Bit of whitespace to indent it */ +.content .method .where::before, .content .fn .where::before { content: ' '; } + +.content .methods > div { margin-left: 40px; } + +.content .impl-items .docblock, .content .impl-items .stability { + margin-left: 40px; +} +.content .impl-items .method, .content .impl-items > .type { + margin-left: 20px; +} + +.content .stability code { + font-size: 90%; +} + +nav { + border-bottom: 1px solid; + padding-bottom: 10px; + margin-bottom: 10px; +} +nav.main { + padding: 20px 0; + text-align: center; +} +nav.main .current { + border-top: 1px solid; + border-bottom: 1px solid; +} +nav.main .separator { + border: 1px solid; + display: inline-block; + height: 23px; + margin: 0 20px; +} +nav.sum { text-align: right; } +nav.sub form { display: inline; } + +nav.sub, .content { + margin-left: 230px; +} + +a { + text-decoration: none; + background: transparent; +} + +.docblock a:hover, .stability a { + text-decoration: underline; +} + +.content span.enum, .content a.enum, .block a.current.enum { color: #5e9766; } +.content span.struct, .content a.struct, .block a.current.struct { color: #df3600; } +.content a.type { color: #e57300; } +.content a.macro { color: #068000; } +.block a.current.crate { font-weight: 500; } + +.search-input { + width: 100%; + /* Override Normalize.css: we have margins and do + not want to overflow - the `moz` attribute is necessary + until Firefox 29, too early to drop at this point */ + -moz-box-sizing: border-box !important; + box-sizing: border-box !important; + outline: none; + border: none; + border-radius: 1px; + margin-top: 5px; + padding: 10px 16px; + font-size: 17px; + transition: border-color 300ms ease; + transition: border-radius 300ms ease-in-out; + transition: box-shadow 300ms ease-in-out; +} + +.search-input:focus { + border-color: #66afe9; + border-radius: 2px; + border: 0; + outline: 0; + box-shadow: 0 0 8px #078dd8; +} + +.search-results .desc { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + display: block; +} + +.search-results a { + display: block; +} + +.content .search-results td:first-child { padding-right: 0; } +.content .search-results td:first-child a { padding-right: 10px; } + +tr.result span.primitive::after { content: ' (primitive type)'; font-style: italic; } + +body.blur > :not(#help) { + filter: blur(8px); + -webkit-filter: blur(8px); + opacity: .7; +} + +#help { + width: 100%; + height: 100vh; + position: fixed; + top: 0; + left: 0; + display: flex; + justify-content: center; + align-items: center; +} +#help > div { + flex: 0 0 auto; + background: #e9e9e9; + box-shadow: 0 0 6px rgba(0,0,0,.2); + width: 550px; + height: 330px; + border: 1px solid #bfbfbf; +} +#help dt { + float: left; + border-radius: 4px; + border: 1px solid #bfbfbf; + background: #fff; + width: 23px; + text-align: center; + clear: left; + display: block; + margin-top: -1px; +} +#help dd { margin: 5px 33px; } +#help .infos { padding-left: 0; } +#help h1, #help h2 { margin-top: 0; } +#help > div div { + width: 50%; + float: left; + padding: 20px; +} + +em.stab { + display: inline-block; + border-width: 1px; + border-style: solid; + padding: 3px; + margin-bottom: 5px; + font-size: 90%; + font-style: normal; +} +em.stab p { + display: inline; +} + +.module-item .stab { + border-width: 0; + padding: 0; + margin: 0; + background: inherit !important; +} + +.module-item.unstable { + opacity: 0.65; +} + +.since { + font-weight: normal; + font-size: initial; + color: grey; + position: absolute; + right: 0; + top: 0; +} + +.variants_table { + width: 100%; +} + +.variants_table tbody tr td:first-child { + width: 1%; /* make the variant name as small as possible */ +} + +td.summary-column { + width: 100%; +} + +.summary { + padding-right: 0px; +} + +.line-numbers :target { background-color: transparent; } + +/* Code highlighting */ +pre.rust .kw { color: #8959A8; } +pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; } +pre.rust .number, pre.rust .string { color: #718C00; } +pre.rust .self, pre.rust .boolval, pre.rust .prelude-val, +pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; } +pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } +pre.rust .lifetime { color: #B76514; } + +.rusttest { display: none; } +pre.rust { position: relative; } +a.test-arrow { + display: inline-block; + position: absolute; + background-color: #4e8bca; + padding: 5px 10px 5px 10px; + border-radius: 5px; + font-size: 130%; + top: 5px; + right: 5px; +} + +.methods .section-header { + /* Override parent class attributes. */ + border-bottom: none !important; + font-size: 1.1em !important; + margin: 0 0 -5px; + padding: 0; +} + +.section-header:hover a:after { + content: '\2002\00a7\2002'; +} + +.section-header:hover a { + text-decoration: none; +} + +.section-header a { + color: inherit; +} + +.collapse-toggle { + font-weight: 300; + position: absolute; + left: -23px; + color: #999; + top: 0; +} + +.toggle-wrapper > .collapse-toggle { + left: -24px; + margin-top: 0px; +} + +.toggle-wrapper { + position: relative; +} + +.toggle-wrapper.collapsed { + height: 1em; + transition: height .2s; +} + +.collapse-toggle > .inner { + display: inline-block; + width: 1.2ch; + text-align: center; +} + +.toggle-label { + color: #999; +} + +.ghost { + display: none; +} + +.ghost + .since { + position: initial; + display: table-cell; +} + +.since + .srclink { + display: table-cell; + padding-left: 10px; +} + +span.since { + position: initial; + font-size: 20px; + margin-right: 5px; +} + +:target > code { + background: #FDFFD3; +} + +/* Media Queries */ + +@media (max-width: 700px) { + body { + padding-top: 0px; + } + + .sidebar { + height: 40px; + min-height: 40px; + width: 100%; + margin: 0px; + padding: 0px; + position: static; + } + + .sidebar .location { + float: right; + margin: 0px; + padding: 3px 10px 1px 10px; + min-height: 39px; + background: inherit; + text-align: left; + font-size: 24px; + } + + .sidebar .location:empty { + padding: 0; + } + + .sidebar img { + width: 35px; + margin-top: 5px; + margin-bottom: 0px; + float: left; + } + + nav.sub { + margin: 0 auto; + } + + .sidebar .block { + display: none; + } + + .content { + margin-left: 0px; + } + + .content .in-band { + width: 100%; + } + + .content .out-of-band { + display: none; + } + + .toggle-wrapper > .collapse-toggle { + left: 0px; + } + + .toggle-wrapper { + height: 1.5em; + } +} + +@media print { + nav.sub, .content .out-of-band, .collapse-toggle { + display: none; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index cbf447534..e9562b5ab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,12 @@ services: volumes: - "/var/run/docker.sock:/var/run/docker.sock" - ".rustwide:/home/cratesfyi/rustwide" + - "cratesio-index:/opt/docsrs/prefix/crates.io-index" environment: CRATESFYI_RUSTWIDE_WORKSPACE: /home/cratesfyi/rustwide + CRATESFYI_DATABASE_URL: postgresql://cratesfyi:password@db + env_file: + - .env db: image: postgres:alpine volumes: @@ -19,4 +23,5 @@ services: POSTGRES_USER: cratesfyi POSTGRES_PASSWORD: password volumes: - postgres-data: + postgres-data: {} + cratesio-index: {} diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 5c284da0a..c2ba355fa 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -2,18 +2,38 @@ set -euv -USER=cratesfyi -BIN=target/release/cratesfyi - -export CRATESFYI_DATABASE_URL=postgresql://cratesfyi:password@db -export CRATESFYI_CONTAINER_NAME=cratesfyi-container -export CRATESFYI_GITHUB_USERNAME= -export CRATESFYI_GITHUB_ACCESSTOKEN= +export CRATESFYI_PREFIX=/opt/docsrs/prefix +export DOCS_RS_DOCKER=true export RUST_LOG=cratesfyi,rustwide=info -export PATH="$PATH:$HOME/docs.rs/target/release" +export PATH="$PATH:/build/target/release" + +# Try migrating the database multiple times if it fails +# This avoids the docker container crashing the first time it's started with +# docker-compose, as PostgreSQL needs some time to initialize. +set +e +failed=0 +while true; do + if ! cratesfyi database migrate; then + ((failed=failed + 1)) + if [ "${failed}" -eq 5 ]; then + exit 1 + fi + echo "failed to migrate the database" + echo "waiting 1 second..." + sleep 1 + else + break + fi +done +set -e + +cratesfyi database update-search-index +cratesfyi database update-release-activity -sudo -E -u $USER $BIN database migrate -sudo -E -u $USER $BIN database update-search-index -sudo -E -u $USER $BIN database update-release-activity +if ! [ -d "${CRATESFYI_PREFIX}/crates.io-index/.git" ]; then + git clone https://github.com/rust-lang/crates.io-index "${CRATESFYI_PREFIX}/crates.io-index" + # Prevent new crates built before the container creation to be built + git --git-dir="$CRATESFYI_PREFIX/crates.io-index/.git" branch crates-index-diff_last-seen +fi -$BIN "$@" +cratesfyi "$@"