Skip to content
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
53 changes: 53 additions & 0 deletions .github/workflows/desktop-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,59 @@ jobs:
echo "Promoted ${RELEASE_TAG} to published (draft=false, latest=false; channel=${CHANNEL})."
fi

# Announce STABLE releases to Slack. Gated on channel=latest so betas
# stay silent — every *-beta.N cut also flows through this job (on
# channel=beta) and must not post (see Detect channel step above).
# Placed AFTER the promote step and gated on success() so we only
# announce a release that is actually published (draft=false), never a
# stuck draft. Skipped on the workflow_dispatch recovery flow so a
# manual DMG re-upload for an older tag does not re-announce it.
#
# The webhook URL lives in the SLACK_WEBHOOK_URL secret on
# inkeep/open-knowledge. When it is absent (a fork, or before the
# secret is provisioned) the step no-ops cleanly; a Slack delivery
# error is downgraded to a ::warning:: — the release is "done" once
# published, so the announcement is strictly best-effort and must
# never fail an otherwise-successful release.
- name: Announce stable release to Slack
if: success() && steps.channel.outputs.channel == 'latest' && github.event_name != 'workflow_dispatch'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
RELEASE_TAG: ${{ github.event.client_payload.release_tag || inputs.release_tag }}
VERSION: ${{ steps.channel.outputs.version }}
run: |
set -euo pipefail
if [[ -z "${SLACK_WEBHOOK_URL:-}" ]]; then
echo "::notice::SLACK_WEBHOOK_URL not set — skipping Slack announcement for ${RELEASE_TAG}."
exit 0
fi
RELEASE_URL="https://github.com/${GITHUB_REPOSITORY}/releases/tag/${RELEASE_TAG}"
# Build the Block Kit payload with jq so $VERSION / $RELEASE_URL are
# JSON-escaped — a stray quote in a tag would otherwise corrupt the
# body. `text` is the notification/a11y fallback Slack recommends
# alongside blocks; the header is plain_text, the section mrkdwn.
payload="$(jq -n \
--arg version "$VERSION" \
--arg release_url "$RELEASE_URL" \
'{
text: ("OpenKnowledge \($version) released — " + $release_url),
blocks: [
{ type: "header",
text: { type: "plain_text", text: "🎉 OpenKnowledge \($version) released", emoji: true } },
{ type: "section",
text: { type: "mrkdwn",
text: ("A new stable release is live.\n\n*<\($release_url)|Release notes & downloads>* · *<https://openknowledge.ai/download|Get the app>*") } }
]
}')"
# The failing curl sits in an `if` condition, which `set -e` does
# not treat as fatal — a Slack outage routes to the else/warning
# and the step still exits 0.
if curl -sS --fail -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK_URL"; then
echo "Posted stable-release announcement for ${RELEASE_TAG} to Slack."
else
echo "::warning::Slack announcement failed for ${RELEASE_TAG} (release is published; notification is best-effort)."
fi

# Lightweight discoverability for stuck-draft state when the promote
# step (or the build/upload step before it) fails. NOT a substitute
# for the full paging-design observability deferred in the PR body —
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/PropertyWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ export function ListWidget({ keyName, value, onCommit }: CommonWidgetProps<strin
data-index={i}
data-tag-invalid={renderAsInvalidTag ? 'true' : undefined}
className={cn(
'inline-flex items-center text-1sm gap-0.5 rounded-full py-0.5 pl-2 pr-1.5 transition-colors',
'inline-flex max-w-full min-w-0 items-center break-all text-1sm gap-0.5 rounded-full py-0.5 pl-2 pr-1.5 transition-colors',
renderAsTag &&
'bg-primary/10 font-medium text-primary has-[button[data-tag]:hover]:bg-primary/20 has-[button[data-tag]:active]:bg-primary/25',
renderAsInvalidTag &&
Expand Down
4 changes: 3 additions & 1 deletion packages/app/src/editor/components/TagDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ export function TagDialog() {
<DialogHeader>
<DialogTitle>
<Trans>
Documents tagged <span className="font-mono">#{tagName}</span>
{/* `break-all` so a long single-word tag breaks mid-string
instead of overflowing the dialog (PRD-7112). */}
Documents tagged <span className="font-mono break-all">#{tagName}</span>
</Trans>
</DialogTitle>
</DialogHeader>
Expand Down
11 changes: 10 additions & 1 deletion packages/app/src/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -4918,7 +4918,16 @@ html.electron-mode [data-slot="sidebar-inner"] {
background-color: color-mix(in oklab, var(--primary) 10%, transparent);
text-decoration: none;
cursor: pointer;
white-space: nowrap;
/* Long-tag containment: no max-width or wrap rules would let a single
* unbroken tag string (`#xxxxxxx...`) blow past the editor's content
* column, the TagDialog body, or the Properties panel value cell —
* PRD-7112's reported "background overflows in weird ways". Cap the
* pill's width at the parent's content box and allow the text to break
* mid-string when (and only when) it would otherwise overflow. Normal-
* length tags don't trigger `overflow-wrap: anywhere` so the single-
* line pill shape is preserved. */
max-width: 100%;
overflow-wrap: anywhere;
vertical-align: baseline;
transition:
background-color 90ms ease,
Expand Down