diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7fe0732 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +# syntax = docker/dockerfile:1 + +# Adjust BUN_VERSION as desired +ARG BUN_VERSION=1.1.0 +FROM oven/bun:${BUN_VERSION}-slim as base + +LABEL fly_launch_runtime="Bun" + +# Bun app lives here +WORKDIR /app + +# Set production environment +ENV NODE_ENV="production" + + +# Throw-away build stage to reduce size of final image +FROM base as build + +# Install packages needed to build node modules +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y build-essential pkg-config python-is-python3 + +# Install node modules +COPY --link bun.lockb package.json ./ +RUN bun install --ci + +# Copy application code +COPY --link . . + + +# Final stage for app image +FROM base + +# Copy built application +COPY --from=build /app /app + +# Start the server by default, this can be overwritten at runtime +EXPOSE 3000 +CMD [ "bun", "index.js" ] diff --git a/bun.lockb b/bun.lockb index 49b3e29..ea3851d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/fly.toml b/fly.toml new file mode 100644 index 0000000..975c69c --- /dev/null +++ b/fly.toml @@ -0,0 +1,23 @@ +# fly.toml app configuration file generated for lum-zulip-plane on 2024-07-23T12:01:40-05:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# + +app = 'lum-zulip-plane' +primary_region = 'ord' + +[deploy] +strategy = 'immediate' + +[build] + +[http_service] + internal_port = 3000 + force_https = true + min_machines_running = 1 + processes = ['app'] + +[[vm]] + memory = '512mb' + cpu_kind = 'shared' + cpus = 1 diff --git a/format.js b/format.js index c37fc0e..b16879e 100644 --- a/format.js +++ b/format.js @@ -98,6 +98,10 @@ export const isIssueEstimateUpdated = e => export const isIssueStateUpdated = e => e.event === 'issue' && e.action === 'updated' && e.activity.field === 'state' +/** @type {(e: Event) => e is EventIssueUpdated<"name">} */ +export const isIssueTitleUpdated = e => + e.event === 'issue' && e.action === 'updated' && e.activity.field === 'name' + /** @type {(c: import('./plane.js').Config, p: string, i: string) => string} */ export const issueURL = (c, project, issue) => c.baseURI + '/' + c.workspace + '/projects/' + project + '/issues/' + issue @@ -125,12 +129,12 @@ export default async (plane, ev) => { /** @type {(_: {sequence_id: number, name: string, project: string, id: string}) => string} */ const link = ({ sequence_id, name, project, id }) => - `**[ATH-${sequence_id}](${issueURL(plane, project, id)}) ${name}**` + `**[CORE-${sequence_id}](${issueURL(plane, project, id)}) ${name}**` const thisLink = link(ev.data) const title = parent ? link(parent) + '\n⤷ ' + link(ev.data) : link(ev.data) const topic = parent - ? 'ATH-' + parent.sequence_id - : 'ATH-' + ev.data.sequence_id + ? 'CORE-' + parent.sequence_id + : 'CORE-' + ev.data.sequence_id /** @type {(g: import('./plane.js').StateGroup) => string} */ const stateEmoji = s => @@ -164,23 +168,10 @@ export default async (plane, ev) => { return ( '**Sub-issues**\n' + by_state('completed') - .map(i => stateEmoji(stateMap[i.state].group) + ' ' + link(i)) - .concat( - by_state('started').map( - i => stateEmoji(stateMap[i.state].group) + ' ' + link(i), - ), - ) - .concat( - by_state('unstarted').map( - i => stateEmoji(stateMap[i.state].group) + ' ' + link(i), - ), - ) - .concat( - by_state('backlog').map( - i => stateEmoji(stateMap[i.state].group) + ' ' + link(i), - ), - ) - .map(l => ' - ' + l) + .concat(by_state('started')) + .concat(by_state('unstarted')) + .concat(by_state('backlog')) + .map(i => ' - ' + stateEmoji(stateMap[i.state].group) + ' ' + link(i)) .join('\n') ) })() @@ -206,6 +197,11 @@ export default async (plane, ev) => { topic, content: `${title}\n${user} set estimate to ${estimateMap[ev.data.estimate_point.toString()]}`, } + } else if (isIssueTitleUpdated(ev)) { + return { + topic, + content: `${title}\n${user} updated title to ${ev.data.name}`, + } } else if (isIssueDescriptionUpdated(ev)) { return { topic, diff --git a/index.js b/index.js index 99f2e19..46151f2 100644 --- a/index.js +++ b/index.js @@ -41,6 +41,8 @@ const server = Bun.serve({ return new Response() }, + hostname: '0.0.0.0', + lowMemoryMode: true, }) console.log(`Zulip <> Plane integration`) diff --git a/package.json b/package.json index 15b8fee..6799148 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "zulip-plane", "module": "index.js", "devDependencies": { + "@flydotio/dockerfile": "^0.5.8", "@types/bun": "latest", "prettier": "^3.3.3", "typescript": "^5.5.4"