Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
68 changes: 65 additions & 3 deletions .github/workflows/manual_release_stable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,79 @@ jobs:
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

version_docs:
name: Version docs
needs: [release_prepare, changelog_update, pypi_publish]
runs-on: ubuntu-latest
permissions:
contents: write
env:
NODE_VERSION: 22
PYTHON_VERSION: 3.14

steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
Comment on lines +120 to +121
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can explicitly checkout the needs.changelog_update.outputs.changelog_commitish, to prevent race conditions or other mishaps?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, checkout now explicitly uses ref: ${{ needs.changelog_update.outputs.changelog_commitish }}


- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Set up uv package manager
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install Python dependencies
run: uv run poe install-dev

- name: Install website dependencies
run: |
cd website
corepack enable
yarn install

- name: Snapshot the current version
run: |
cd website
VERSION="$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('../pyproject.toml').read_text())['project']['version'])")"
MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)"
export MAJOR_MINOR
# Remove existing version if present (patch releases override)
rm -rf "versioned_docs/version-${MAJOR_MINOR}"
rm -rf "versioned_sidebars/version-${MAJOR_MINOR}-sidebars.json"
jq 'map(select(. != env.MAJOR_MINOR))' versions.json > tmp.json && mv tmp.json versions.json
# Build API reference and create version snapshots
bash build_api_reference.sh
npx docusaurus docs:version "$MAJOR_MINOR"
npx docusaurus api:version "$MAJOR_MINOR"

- name: Commit and push versioned docs
uses: EndBug/add-and-commit@v9
with:
add: "website/versioned_docs website/versioned_sidebars website/versions.json"
message: "docs: version ${{ needs.release_prepare.outputs.version_number }} docs [skip ci]"
default_author: github_actions

doc_release:
name: Doc release
needs: [changelog_update, pypi_publish]
needs: [changelog_update, pypi_publish, version_docs]
permissions:
contents: write
pages: write
id-token: write
uses: ./.github/workflows/_release_docs.yaml
with:
# Use the ref from the changelog update to include the updated changelog.
ref: ${{ needs.changelog_update.outputs.changelog_commitish }}
# Use the default branch ref to include both changelog and versioned docs.
ref: ${{ github.ref }}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as GitHub docs are concerned (link), github.ref ...is the branch or tag ref that triggered the workflow run.

If I understand correctly, this will be the commit that this workflow_dispatch was invoked on, without the changelog and versioned docs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks, fixed - now it uses needs.version_docs.outputs.version_docs_commitish which should include both changelog and versioned docs.

secrets: inherit

trigger_docker_build:
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ allow-direct-references = true
[tool.ruff]
line-length = 120
include = ["src/**/*.py", "tests/**/*.py", "docs/**/*.py", "website/**/*.py"]
exclude = [
"website/versioned_docs/**",
]

[tool.ruff.lint]
select = ["ALL"]
Expand Down Expand Up @@ -201,6 +204,7 @@ python-version = "3.10"

[tool.ty.src]
include = ["src", "tests", "scripts", "docs", "website"]
exclude = ["website/versioned_docs"]

[[tool.ty.overrides]]
include = [
Expand Down
17 changes: 17 additions & 0 deletions website/build_api_reference.sh
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are these changes connected to the rest of the PR? IIRC this is done automatically by docusaurus-plugin-typedoc-api 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, this should follow the same pattern as in apify-client-python, if I undo these changes and remove the transform docs script and pydoc markdown yaml it does not work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I tried a bit more, they are gone and I'll remove them from the Client's docs as well, thanks!

Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
#!/bin/bash

# On macOS, sed requires a space between -i and '' to specify no backup should be done
# On Linux, sed requires no space between -i and '' to specify no backup should be done
sed_no_backup() {
if [[ $(uname) = "Darwin" ]]; then
sed -i '' "$@"
else
sed -i'' "$@"
fi
}

# Create docspec dump of this package's source code through pydoc-markdown
pydoc-markdown --quiet --dump > docspec-dump.jsonl
sed_no_backup "s#${PWD}/..#REPO_ROOT_PLACEHOLDER#g" docspec-dump.jsonl

# Generate import shortcuts from the modules
python generate_module_shortcuts.py

# Transform the docspec dumps into Typedoc-compatible docs tree
node transformDocs.js
20 changes: 20 additions & 0 deletions website/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { join, resolve } = require('node:path');
const { config } = require('@apify/docs-theme');

const { externalLinkProcessor } = require('./tools/utils/externalLink');
const versions = require('./versions.json');

const GROUP_ORDER = [
'Actor',
Expand Down Expand Up @@ -88,6 +89,17 @@ module.exports = {
label: 'GitHub',
position: 'left',
},
{
type: 'docsVersionDropdown',
position: 'left',
className: 'navbar__item',
'data-api-links': JSON.stringify([
'reference/next',
...versions.map((version, i) => (i === 0 ? 'reference' : `reference/${version}`)),
]),
dropdownItemsBefore: [],
dropdownItemsAfter: [],
},
],
},
},
Expand Down Expand Up @@ -121,6 +133,7 @@ module.exports = {
typedocOptions: {
excludeExternals: false,
},
pathToCurrentVersionTypedocJSON: `${__dirname}/api-typedoc-generated.json`,
sortSidebar: groupSort,
routeBasePath: 'reference',
python: true,
Expand Down Expand Up @@ -280,13 +293,20 @@ module.exports = {
includeGeneratedIndex: false,
includePages: true,
relativePaths: false,
excludeRoutes: [
'/sdk/python/reference/[0-9]*/**',
'/sdk/python/reference/[0-9]*',
'/sdk/python/reference/next/**',
'/sdk/python/reference/next',
],
},
},
],
...config.plugins,
],
themeConfig: {
...config.themeConfig,
versions,
tableOfContents: {
...config.themeConfig.tableOfContents,
maxHeadingLevel: 5,
Expand Down
13 changes: 13 additions & 0 deletions website/pydoc-markdown.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
loaders:
- type: python
search_path: [../src]
processors:
- type: filter
skip_empty_modules: true
- type: crossref
renderer:
type: docusaurus
docs_base_path: docs
relative_output_path: reference
relative_sidebar_path: sidebar.json
sidebar_top_level_label: null
94 changes: 94 additions & 0 deletions website/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import { useVersions, useActiveDocContext, useDocsVersionCandidates } from '@docusaurus/plugin-content-docs/client';
import { useDocsPreferredVersion } from '@docusaurus/theme-common';
import { translate } from '@docusaurus/Translate';
import { useLocation } from '@docusaurus/router';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';

const getVersionMainDoc = (version) => version.docs.find((doc) => doc.id === version.mainDocId);

function getApiLinks(props, pathname, baseUrl) {
if (!pathname.startsWith(`${baseUrl}reference`)) {
return [];
}

try {
return JSON.parse(props['data-api-links']);
} catch {
return [];
}
}

/* eslint-disable react/prop-types */
export default function DocsVersionDropdownNavbarItem({
mobile,
docsPluginId,
dropdownActiveClassDisabled,
dropdownItemsBefore,
dropdownItemsAfter,
...props
}) {
const { search, hash, pathname } = useLocation();
const { siteConfig } = useDocusaurusContext();
const baseUrl = siteConfig.baseUrl.endsWith('/') ? siteConfig.baseUrl : `${siteConfig.baseUrl}/`;
const apiLinks = getApiLinks(props, pathname, baseUrl);

const activeDocContext = useActiveDocContext(docsPluginId);
const versions = useVersions(docsPluginId);
const { savePreferredVersionName } = useDocsPreferredVersion(docsPluginId);
const versionLinks = versions.map((version, idx) => {
// We try to link to the same doc, in another version
// When not possible, fallback to the "main doc" of the version
const versionDoc = activeDocContext.alternateDocVersions[version.name] ?? getVersionMainDoc(version);
return {
label: version.label,
// preserve ?search#hash suffix on version switches
to: `${apiLinks[idx] ?? versionDoc.path}${search}${hash}`,
isActive: () => version === activeDocContext.activeVersion,
onClick: () => savePreferredVersionName(version.name),
};
});
const items = [...dropdownItemsBefore, ...versionLinks, ...dropdownItemsAfter];
const dropdownVersion = useDocsVersionCandidates(docsPluginId)[0];
// Mobile dropdown is handled a bit differently
const dropdownLabel =
mobile && items.length > 1
? translate({
id: 'theme.navbar.mobileVersionsDropdown.label',
message: 'Versions',
description: 'The label for the navbar versions dropdown on mobile view',
})
: dropdownVersion.label;
let dropdownTo = mobile && items.length > 1 ? undefined : getVersionMainDoc(dropdownVersion).path;

if (dropdownTo && pathname.startsWith(`${baseUrl}reference`)) {
dropdownTo = versionLinks.find((v) => v.label === dropdownVersion.label)?.to;
}

// We don't want to render a version dropdown with 0 or 1 item. If we build
// the site with a single docs version (onlyIncludeVersions: ['1.0.0']),
// We'd rather render a button instead of a dropdown
if (items.length <= 1) {
return (
<DefaultNavbarItem
{...props}
mobile={mobile}
label={dropdownLabel}
to={dropdownTo}
isActive={dropdownActiveClassDisabled ? () => false : undefined}
/>
);
}
return (
<DropdownNavbarItem
{...props}
mobile={mobile}
label={dropdownLabel}
to={dropdownTo}
items={items}
isActive={dropdownActiveClassDisabled ? () => false : undefined}
/>
);
}
Loading
Loading