Skip to content

Updated Auto-Redirect Flow for Segments #1339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 10, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
45 changes: 24 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,21 @@ No actions required - the new content will be automatically reflected in both Ar

### Switching Between GitOps (ArgoHub) and Enterprise Segments

By default, users are redirected from the Enterprise segment to the GitOps (ArgoHub) segment.
By default, users are redirected from the Enterprise segment to the GitOps (ArgoHub) segment.

#### Example:

- Accessing https://codefresh.io/docs/ will redirect to https://codefresh.io/docs/gitops/

For more details, refer to the "Auto Redirect from Enterprise to ArgoHub Collection" section below.

#### To switch segments in production:

- To switch to the GitOps segment, log in to Codefresh and switch to an account with the GitOps type. This will clear the Enterprise cookie.
- To switch to the Enterprise segment, log in to Codefresh and switch to an account with any other type. This will set the Enterprise cookie.

#### To switch segments in local development:
#### Switching Between Segments

In the local documentation site (`http://localhost:3131/`), open the console in developer tools and inject the appropriate cookie:
- Use the segment dropdown menu in the page header to select a segment.
- Use a cookie to automatically switch segments (production only):

- **Switch to Enterprise Segment:**
```js
document.cookie = 'cfdoctype=enterprise; SameSite=Strict; Domain=localhost; Max-age=2592000; Path=/';
```

- **Switch to GitOps Segment:**
```js
document.cookie = 'cfdoctype=enterprise; SameSite=Strict; Domain=localhost; Max-age=0; Path=/';
```
- **To switch to the GitOps segment:** Log in to Codefresh and switch to an account with the GitOps type. This will set the GitOps cookie.
- **To switch to the Enterprise segment:** Log in to Codefresh and switch to an account with any other type. This will clear the GitOps cookie.

### Reusing Existing Documents

Expand Down Expand Up @@ -128,13 +118,26 @@ The ArgoHub home page and all pages within the ArgoHub collection are excluded f

- Commandbar HelpHub Search (managed via Commandbar Content Manager).
- Search engines that support the `noindex` rule, such as Google.
- All pages in the `gitops` collection, including the home page, are excluded from the Sitemap.xml file.

### Auto-Redirect: Enterprise to ArgoHub Collection

The documentation site automatically redirects users from any Enterprise page to the corresponding GitOps (ArgoHub) page when the GitOps cookie is present.

#### Commandbar's HelpHub and Copilot Content Sync
#### Redirect Logic

Commandbar synchronizes the documentation site content using a crawler. However, the Auto Redirect mechanism prevents the crawler from accessing all Enterprise pages (see the "Auto Redirect from Enterprise to ArgoHub Collection" section for details). To address this issue, the Commandbar team configured the crawler to include the `cfdoctype` cookie, enabling it to access all documentation pages and bypass the redirect.
```mermaid
flowchart LR
A[Enterprise Page] --> B{GitOps Cookie Present?}
B -->|No| C[Stay on Enterprise Page]
B -->|Yes| D[Redirect to GitOps Page]
```

### Auto Redirect from Enterprise to ArgoHub Collection
```mermaid
flowchart LR
A[GitOps Page] --> B[Stay on GitOps Page]
```

When the GitOps client adds an ArgoHub system type cookie, the Documentation site will detect it and initiate an automatic redirect. If you open any page from the enterprise collection, the site will check for an equivalent document in the ArgoHub collection and redirect you there if one exists.
#### Redirect Mapping

Redirect links between the Enterprise and ArgoHub collections are stored in the `argohub-redirect-mapping.json` file. Running `npm run link` automatically updates the file, eliminating the need for manual updates.
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ defaults:
type: gitops
values:
layout: gitops
sitemap: false
toc: true
wide: true

Expand Down
105 changes: 1 addition & 104 deletions _includes/scripts.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@
<!-- End of Doc Search Embed Code -->

<script>
const isEnterpriseDocumentationCookieSet = document.cookie.includes('cfdoctype=enterprise')
const commandbarSegment = isEnterpriseDocumentationCookieSet ? '3033bf7f' : '43836ac3'
const commandbarSegment = IS_GITOPS_DOC_COOKIE_SET ? '43836ac3': '3033bf7f'

var o=commandbarSegment,n=["Object.assign","Symbol","Symbol.for"].join("%2C"),a=window;function r(o,n){void 0===n&&(n=!1),"complete"!==document.readyState&&window.addEventListener("load",r.bind(null,o,n),{capture:!1,once:!0});var a=document.createElement("script");a.type="text/javascript",a.async=n,a.src=o,document.head.appendChild(a)}function t(){var n;if(void 0===a.CommandBar){delete a.__CommandBarBootstrap__;var t=Symbol.for("CommandBar::configuration"),e=Symbol.for("CommandBar::orgConfig"),i=Symbol.for("CommandBar::disposed"),c=Symbol.for("CommandBar::isProxy"),m=Symbol.for("CommandBar::queue"),d=Symbol.for("CommandBar::unwrap"),l=Symbol.for("CommandBar::eventSubscriptions"),s=[],u=localStorage.getItem("commandbar.lc"),f=u&&u.includes("local")?"http://localhost:8000":"https://api.commandbar.com",p=Object.assign(((n={})[t]={uuid:o},n[e]={},n[i]=!1,n[c]=!0,n[m]=new Array,n[d]=function(){return p},n[l]=void 0,n),a.CommandBar),b=["addCommand","boot","addEventSubscriber","addRecordAction","setFormFactor"],y=p;Object.assign(p,{shareCallbacks:function(){return{}},shareContext:function(){return{}}}),a.CommandBar=new Proxy(p,{get:function(o,n){return n in y?p[n]:"then"!==n?b.includes(n)?function(){var o=Array.prototype.slice.call(arguments);return new Promise((function(a,r){o.unshift(n,a,r),p[m].push(o)}))}:function(){var o=Array.prototype.slice.call(arguments);o.unshift(n),p[m].push(o)}:void 0}}),null!==u&&s.push("lc=".concat(u)),s.push("version=2"),r("".concat(f,"/latest/").concat(o,"?").concat(s.join("&")),!0)}}void 0===Object.assign||"undefined"==typeof Symbol||void 0===Symbol.for?(a.__CommandBarBootstrap__=t,r("https://polyfill.io/v3/polyfill.min.js?version=3.101.0&callback=__CommandBarBootstrap__&features="+n)):t();
window.CommandBar.setThemeMode('dark_mode')
Expand All @@ -81,105 +80,3 @@
}
});
</script>

<script>
toggleSegmentDropdown = function() {
const select = document.querySelector('.custom-select');
select.classList.toggle('open');
};

handleDropdownKeydown = function (event) {
const select = document.querySelector('.custom-select');
const options = select.querySelectorAll('.option');
const isOpen = select.classList.contains('open');

switch (event.key) {
case 'Enter':
case ' ':
event.preventDefault();
toggleSegmentDropdown();
break;
case 'ArrowDown':
event.preventDefault();
if (!isOpen) toggleSegmentDropdown();
options[0].focus();
break;
case 'Escape':
if (isOpen) toggleSegmentDropdown();
break;
}
};

handleOptionKeydown = function (event, option, selectedValue) {
const select = document.querySelector('.custom-select');
const options = select.querySelectorAll('.option');
const currentIndex = Array.from(options).indexOf(option);

switch (event.key) {
case 'Enter':
case ' ':
event.preventDefault();
selectSegmentOption(option, selectedValue);
break;
case 'ArrowDown':
event.preventDefault();
if (currentIndex < options.length - 1) {
options[currentIndex + 1].focus();
}
break;
case 'ArrowUp':
event.preventDefault();
if (currentIndex > 0) {
options[currentIndex - 1].focus();
}
break;
case 'Escape':
select.classList.remove('open');
select.querySelector('.select-display').focus();
break;
}
};

selectSegmentOption = async function (option, selectedValue) {
const selectDisplay = document.querySelector('.select-display');

selectDisplay.textContent = option.textContent;

const redirectMap = await fetchRedirectMap();

const pathname = window.location.pathname;
const currentPath = pathname.replace(SITE_BASE_URL, "");

if (selectedValue === 'enterprise') {
localStorage.setItem(enterpriseDocTypeLockKey, 'true');

const enterprisePath = Object.keys(redirectMap).find(
key => redirectMap[key] === currentPath
);

if (enterprisePath) {
window.location.href = `${SITE_BASE_URL}${enterprisePath}`;
} else {
window.location.href = `${SITE_BASE_URL}/`;
}
} else if (selectedValue === 'gitops') {
localStorage.setItem(enterpriseDocTypeLockKey, 'false');

const gitOpsPath = redirectMap[currentPath];

if (gitOpsPath) {
window.location.href = `${SITE_BASE_URL}${gitOpsPath}`;
} else {
window.location.href = `${SITE_BASE_URL}/${SITE_GITOPS_COLLECTION}/`;
}
}
};
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
const select = document.querySelector('.custom-select');
if (!select.contains(e.target)) {
select.classList.remove('open');
}
});
</script>

165 changes: 132 additions & 33 deletions assets/js/src/argohub-redirect.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,157 @@
const enterpriseDocumentationCookie = "cfdoctype=enterprise";
const ARGOHUB_MAIN_PATH = `/${SITE_GITOPS_COLLECTION}/`;
const enterpriseDocTypeLockKey = "enterpriseDocTypeLock";
const GITOPS_DOC_COOKIE = 'cfdoctype=gitops'
const IS_GITOPS_DOC_COOKIE_SET = document.cookie.includes(GITOPS_DOC_COOKIE)

function checkIfEnterpriseDocumentationCookieSet() {
return document.cookie.includes(enterpriseDocumentationCookie);
}
handleRedirect()

async function getArgoHubRedirectURL(currentPath) {
currentPath = currentPath.replace(SITE_BASE_URL, "");
currentPath = currentPath.replace(SITE_BASE_URL, '')

const redirectMap = await fetchRedirectMap();
const redirectMap = await fetchRedirectMap()

const newPath = redirectMap[currentPath];
if (!newPath) return null;
const newPath = redirectMap[currentPath]
if (!newPath) return null

const newURL =
newPath === ARGOHUB_MAIN_PATH
newPath === `/${SITE_GITOPS_COLLECTION}/`
? `${location.href}${SITE_GITOPS_COLLECTION}`
: location.href.replace(currentPath, newPath);
: location.href.replace(currentPath, newPath)

return newURL;
return newURL
}

async function handleRedirect() {
if (shouldSkipRedirect()) return;
Copy link
Contributor

Choose a reason for hiding this comment

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

if gitops cookie is removed, but user is trying to reach gitops page, we will not redirect him to enterprise?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At this stage, we will maintain a one-way redirect and extend it if necessary.

if (SITE_IS_GITOPS_COLLECTION || !IS_GITOPS_DOC_COOKIE_SET) return

const argoHubRedirectURL = await getArgoHubRedirectURL(location.pathname);
if (!argoHubRedirectURL) return;
const argoHubRedirectURL = await getArgoHubRedirectURL(location.pathname)
if (!argoHubRedirectURL) return

location.href = argoHubRedirectURL;
location.href = argoHubRedirectURL
}

async function fetchRedirectMap() {
const response = await fetch(
`${SITE_BASE_URL}/assets/js/src/argohub-redirect-mapping.json`
);
const response = await fetch(`${SITE_BASE_URL}/assets/js/src/argohub-redirect-mapping.json`)
if (!response.ok) {
throw new Error("Failed to fetch the collections redirect map.");
throw new Error('Failed to fetch the collections redirect map.')
}
return response.json()
}

function setGitOpsDocumentationCookie() {
const maxAge = 2592000
configureGitOpsDocumentationCookie(maxAge)
}

function removeGitOpsDocumentationCookie() {
configureGitOpsDocumentationCookie(0)
}

function configureGitOpsDocumentationCookie(maxAge) {
let cookie = `${GITOPS_DOC_COOKIE}; Max-Age=${maxAge}; Path=/; SameSite=Strict`

if (location.protocol === 'https:') {
cookie += '; Secure'
}

if (location.hostname.endsWith('.codefresh.io')) {
cookie += '; Domain=.codefresh.io'
}

document.cookie = cookie
}

function toggleSegmentDropdown() {
const select = document.querySelector('.custom-select')
select.classList.toggle('open')
}

function handleDropdownKeydown(event) {
const select = document.querySelector('.custom-select')
const options = select.querySelectorAll('.option')
const isOpen = select.classList.contains('open')

switch (event.key) {
case 'Enter':
case ' ':
event.preventDefault()
toggleSegmentDropdown()
break
case 'ArrowDown':
event.preventDefault()
if (!isOpen) toggleSegmentDropdown()
options[0].focus()
break
case 'Escape':
if (isOpen) toggleSegmentDropdown()
break
}
return response.json();
}

function isEnterpriseLockPresent() {
const enterpriseDocTypeLock = localStorage.getItem(enterpriseDocTypeLockKey);
return !!enterpriseDocTypeLock;
function handleOptionKeydown(event, option, selectedValue) {
const select = document.querySelector('.custom-select')
const options = select.querySelectorAll('.option')
const currentIndex = Array.from(options).indexOf(option)

switch (event.key) {
case 'Enter':
case ' ':
event.preventDefault()
selectSegmentOption(option, selectedValue)
break
case 'ArrowDown':
event.preventDefault()
if (currentIndex < options.length - 1) {
options[currentIndex + 1].focus()
}
break
case 'ArrowUp':
event.preventDefault()
if (currentIndex > 0) {
options[currentIndex - 1].focus()
}
break
case 'Escape':
select.classList.remove('open')
select.querySelector('.select-display').focus()
break
}
}

function shouldSkipRedirect() {
return true; // Redirect temporarily disabled. Will be re-enabled with a new cookie-based mechanism.
// return (
// isEnterpriseLockPresent() ||
// SITE_IS_GITOPS_COLLECTION ||
// checkIfEnterpriseDocumentationCookieSet()
// );
async function selectSegmentOption(option, selectedValue) {
const selectDisplay = document.querySelector('.select-display')

selectDisplay.textContent = option.textContent

const redirectMap = await fetchRedirectMap()

const pathname = window.location.pathname
const currentPath = pathname.replace(SITE_BASE_URL, '')

if (selectedValue === 'enterprise') {
removeGitOpsDocumentationCookie()

const enterprisePath = Object.keys(redirectMap).find((key) => redirectMap[key] === currentPath)

if (enterprisePath) {
window.location.href = `${SITE_BASE_URL}${enterprisePath}`
} else {
window.location.href = `${SITE_BASE_URL}/`
}
} else if (selectedValue === 'gitops') {
setGitOpsDocumentationCookie()

const gitOpsPath = redirectMap[currentPath]

if (gitOpsPath) {
window.location.href = `${SITE_BASE_URL}${gitOpsPath}`
} else {
window.location.href = `${SITE_BASE_URL}/${SITE_GITOPS_COLLECTION}/`
}
}
}

handleRedirect();
document.addEventListener('click', (e) => {
const select = document.querySelector('.custom-select')
if (!select.contains(e.target)) {
select.classList.remove('open')
}
})
1 change: 1 addition & 0 deletions gitops/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
layout: home
title: GitOps Home
sitemap: false
---

<main class="bd-masthead bd-masthead-home" id="content" role="main">
Expand Down