diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 48d3d9a43..d3049b75a 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -598,6 +598,49 @@ jobs: with: name: changelog path: ${{ env.ARTIFACTS_RAW_DIR }}/changelog/ + - name: Prepare docs push + id: docs-push-infos + run: | + if [[ ${{ secrets.AWS_REPO_PREPROD_DOCUMENTATION_BUCKET_NAME }} != "" ]] && \ + [[ ${{ secrets.AWS_REPO_PREPROD_DOCUMENTATION_DISTRIBUTION_ID }} != "" ]] && \ + [[ "${IS_PRERELEASE}" == "true" ]]; then + echo "::set-output name=aws-bucket::${{ secrets.AWS_REPO_PREPROD_DOCUMENTATION_BUCKET_NAME }}" + echo "::set-output name=aws-distribution::${{ secrets.AWS_REPO_PREPROD_DOCUMENTATION_DISTRIBUTION_ID }}" + else + echo "::set-output name=aws-bucket::${{ secrets.AWS_REPO_DOCUMENTATION_BUCKET_NAME }}" + echo "::set-output name=aws-distribution::${{ secrets.AWS_REPO_DOCUMENTATION_DISTRIBUTION_ID }}" + fi + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@0d9a5be0dceea74e09396820e1e522ba4a110d2f + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + - name: Update versions.html for docs + if: ${{ success() && !cancelled() }} + run: | + DOWNLOADED_HTML_FILE=$(mktemp --suffix=.html) + OUTPUT_HTML_FILE=$(mktemp --suffix=.html) + + aws s3api get-object \ + --bucket ${{ steps.docs-push-infos.outputs.aws-bucket }} \ + --key concretefhe/versions.html "${DOWNLOADED_HTML_FILE}" + + python3 ./script/actions_utils/generate_versions_html.py \ + --add-versions "${PROJECT_VERSION}" \ + --versions-html-file "${DOWNLOADED_HTML_FILE}" \ + --output-html "${OUTPUT_HTML_FILE}" + + aws s3 cp "${OUTPUT_HTML_FILE}" \ + s3://${{ steps.docs-push-infos.outputs.aws-bucket }}/concretefhe/versions.html \ + --acl public-read + + aws cloudfront create-invalidation \ + --distribution-id ${{ steps.docs-push-infos.outputs.aws-distribution }} \ + --paths /concretefhe/versions.html + + # Copy to docs to keep a version in docs artifacts + cp "${OUTPUT_HTML_FILE}" "${RAW_DOCS_DIR}"/versions.html - name: Create ready to upload/packaged artifacts and release body if: ${{ success() && !cancelled() }} env: @@ -607,6 +650,8 @@ jobs: pushd "${RAW_DOCS_DIR}" zip -r "${ARTIFACTS_PACKAGED_DIR}/html-docs.zip" ./* tar -cvzf "${ARTIFACTS_PACKAGED_DIR}/html-docs.tar.gz" ./* + # Remove the versions.html to avoid pushing it to S3 but have it in release artifacts + rm versions.html popd cp "${RAW_CHANGELOG_DIR}"/* "${ARTIFACTS_PACKAGED_DIR}" ls -a "${ARTIFACTS_PACKAGED_DIR}" @@ -615,26 +660,20 @@ jobs: echo "RELEASE_BODY_FILE=${RELEASE_BODY_FILE}" >> "$GITHUB_ENV" cp ./script/actions_utils/RELEASE_TEMPLATE.md "${RELEASE_BODY_FILE}" - echo "Docker Image: ${RELEASE_IMG_GIT_TAG}" >> "${RELEASE_BODY_FILE}" - if [[ "${IS_PRERELEASE}" == "false" ]]; then - echo "Documentation: https://docs.zama.ai/concretefhe/${PROJECT_VERSION}" >> "${RELEASE_BODY_FILE}" - fi - echo "" >> "${RELEASE_BODY_FILE}" + { + echo "Docker Image: ${RELEASE_IMG_GIT_TAG}"; + echo "Documentation: https://${{ steps.docs-push-infos.outputs.aws-bucket }}/concretefhe/${PROJECT_VERSION}"; + echo ""; + } >> "${RELEASE_BODY_FILE}" cat "${RAW_CHANGELOG_DIR}"/* >> "${RELEASE_BODY_FILE}" - name: Push release docker image if: ${{ success() && !cancelled() }} run: | docker image push --all-tags "${RELEASE_IMAGE_BASE}" - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@0d9a5be0dceea74e09396820e1e522ba4a110d2f - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} - name: Push release documentation - if: ${{ success() && !cancelled() && !fromJSON(env.IS_PRERELEASE) }} + if: ${{ success() && !cancelled() }} env: - AWS_S3_BUCKET: ${{ secrets.AWS_REPO_DOCUMENTATION_BUCKET_NAME }} + AWS_S3_BUCKET: ${{ steps.docs-push-infos.outputs.aws-bucket }} SOURCE_DIR: ${{ steps.download-docs.outputs.download-path }} DEST_DIR: 'concretefhe/${{ env.PROJECT_VERSION }}' run: | @@ -643,7 +682,7 @@ jobs: - name: Push release documentation as stable if: ${{ success() && !cancelled() && !fromJSON(env.IS_PRERELEASE) && fromJSON(env.IS_LATEST) }} env: - AWS_S3_BUCKET: ${{ secrets.AWS_REPO_DOCUMENTATION_BUCKET_NAME }} + AWS_S3_BUCKET: ${{ steps.docs-push-infos.outputs.aws-bucket }} SOURCE_DIR: ${{ steps.download-docs.outputs.download-path }} DEST_DIR: 'concretefhe/stable' run: | @@ -652,7 +691,7 @@ jobs: if: ${{ success() && !fromJSON(env.IS_PRERELEASE) && fromJSON(env.IS_LATEST) }} env: SOURCE_PATH: "/concretefhe/stable/*" - DISTRIBUTION_ID: ${{ secrets.AWS_REPO_DOCUMENTATION_DISTRIBUTION_ID }} + DISTRIBUTION_ID: ${{ steps.docs-push-infos.outputs.aws-distribution }} run: | aws cloudfront create-invalidation \ --distribution-id "${DISTRIBUTION_ID}" \ diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html new file mode 100644 index 000000000..8c221c407 --- /dev/null +++ b/docs/_templates/versions.html @@ -0,0 +1,28 @@ + + + + + + + +
+
+

+ ConcreteFHE Documentation +

+
+

+ + Pick a version + +

+ +
+
+
+ + diff --git a/docs/versions.html b/docs/versions.html deleted file mode 100644 index 7f3b15535..000000000 --- a/docs/versions.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - -
-
-

ConcreteFHE Documentation

-
-

Pick a version

- -
-
-
- - diff --git a/script/actions_utils/generate_versions_html.py b/script/actions_utils/generate_versions_html.py new file mode 100644 index 000000000..6ed0b43c0 --- /dev/null +++ b/script/actions_utils/generate_versions_html.py @@ -0,0 +1,160 @@ +"""Tool to manage the versions.html file at the root of our docs sites.""" + +import argparse +from pathlib import Path + +from bs4 import BeautifulSoup +from bs4.element import Tag +from semver import VersionInfo + +VERSIONS_LIST_ID = "versions-list" + + +def strip_leading_v(version_str: str): + """Strip leading v of a version which is not SemVer compatible.""" + return version_str[1:] if version_str.startswith("v") else version_str + + +def create_list_element(soup: BeautifulSoup, contents: Tag) -> Tag: + """Create a list element for links. + + Args: + soup (BeautifulSoup): The soup to use to create the tag. + + Returns: + Tag: tag containing
  • . + """ + new_list_element = soup.new_tag("li", **{"class": "toctree-l1"}) + new_list_element.contents.append(contents) + return new_list_element + + +def create_link_tag_set_string(soup: BeautifulSoup, version_string: str) -> Tag: + """Create a link tag on the given soup to version specified by version_string. + + Args: + soup (BeautifulSoup): The soup to use to create the tag. + version_string (str): The version string to use. + + Returns: + Tag: tag containing {version_string}. + """ + new_tag = soup.new_tag( + "a", + **{ + "href": f"{version_string}/", + "class": "reference internal", + }, + ) + + new_tag.string = version_string + return new_tag + + +def main(args): + """Entry point.""" + + invalid_versions = [ + version + for version in args.add_versions + if not VersionInfo.isvalid(strip_leading_v(version)) + ] + if len(invalid_versions) > 0: + raise RuntimeError(f"Found invalid versions: {invalid_versions}") + + version_html = None + version_html_file_path = Path(args.versions_html_file).resolve() + with open(version_html_file_path, "r", encoding="utf-8") as f: + version_html = BeautifulSoup(f, "html.parser") + + if version_html is None: + raise RuntimeError(f"An error occured while trying to load {str(version_html_file_path)}") + + print(version_html) + + version_list = version_html.find(id=VERSIONS_LIST_ID) + if version_list is None or version_list.name != "ul": + raise RuntimeError(f"Could not find