diff --git a/.changeset/techdocs-poor-forks-repeat.md b/.changeset/techdocs-poor-forks-repeat.md new file mode 100644 index 0000000000..89c4e0dc5a --- /dev/null +++ b/.changeset/techdocs-poor-forks-repeat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Return a `304 Not Modified` from the `/sync/:namespace/:kind/:name` endpoint if nothing was built. This enables the caller to know whether a refresh of the docs page will return updated content (-> `201 Created`) or not (-> `304 Not Modified`). diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index dce391ff3f..24549f8b6f 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -68,7 +68,11 @@ export class DocsBuilder { this.config = config; } - public async build(): Promise { + /** + * Build the docs and return whether they have been newly generated or have been cached + * @returns true, if the docs have been built. false, if the cached docs are still up-to-date. + */ + public async build(): Promise { if (!this.entity.metadata.uid) { throw new Error( 'Trying to build documentation for entity not in service catalog', @@ -125,7 +129,7 @@ export class DocsBuilder { this.entity, )} are unmodified. Using cache, skipping generate and prepare`, ); - return; + return false; } throw new Error(err.message); } @@ -205,5 +209,7 @@ export class DocsBuilder { // Update the last check time for the entity new BuildMetadataStorage(this.entity.metadata.uid).setLastUpdated(); + + return true; } } diff --git a/plugins/techdocs-backend/src/service/router.ts b/plugins/techdocs-backend/src/service/router.ts index 1cd4075da0..1a8bdb9c8f 100644 --- a/plugins/techdocs-backend/src/service/router.ts +++ b/plugins/techdocs-backend/src/service/router.ts @@ -16,7 +16,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { NotFoundError } from '@backstage/errors'; +import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { GeneratorBuilder, getLocationForEntity, @@ -172,10 +172,10 @@ export async function createRouter({ case 'awsS3': case 'azureBlobStorage': case 'openStackSwift': - case 'googleGcs': + case 'googleGcs': { // This block should be valid for all storage implementations. So no need to duplicate in future, // add the publisher type in the list here. - await docsBuilder.build(); + const updated = await docsBuilder.build(); // With a maximum of ~5 seconds wait, check if the files got published and if docs will be fetched // on the user's page. If not, respond with a message asking them to check back later. // The delay here is to make sure GCS/AWS/etc. registers newly uploaded files which is usually <1 second @@ -194,10 +194,17 @@ export async function createRouter({ 'Sorry! It took too long for the generated docs to show up in storage. Check back later.', ); } + + if (!updated) { + throw new NotModifiedError(); + } + res .status(201) .json({ message: 'Docs updated or did not need updating' }); break; + } + default: throw new NotFoundError( `Publisher type ${publisherType} is not supported by techdocs-backend docs builder.`,