{"id":18263837,"url":"https://github.com/atomist/sdm-pack-lifecycle","last_synced_at":"2025-04-09T01:28:36.963Z","repository":{"id":57099632,"uuid":"187201534","full_name":"atomist/sdm-pack-lifecycle","owner":"atomist","description":"Extension pack to add lifecycle support into an SDM","archived":false,"fork":false,"pushed_at":"2021-06-09T11:54:11.000Z","size":2140,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T18:56:05.779Z","etag":null,"topics":["node"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atomist.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null}},"created_at":"2019-05-17T11:04:00.000Z","updated_at":"2021-06-09T11:52:25.000Z","dependencies_parsed_at":"2022-08-20T16:50:58.350Z","dependency_job_id":null,"html_url":"https://github.com/atomist/sdm-pack-lifecycle","commit_stats":null,"previous_names":[],"tags_count":451,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomist%2Fsdm-pack-lifecycle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomist%2Fsdm-pack-lifecycle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomist%2Fsdm-pack-lifecycle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomist%2Fsdm-pack-lifecycle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomist","download_url":"https://codeload.github.com/atomist/sdm-pack-lifecycle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247955965,"owners_count":21024489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["node"],"created_at":"2024-11-05T11:12:52.958Z","updated_at":"2025-04-09T01:28:36.944Z","avatar_url":"https://github.com/atomist.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @atomist/sdm-pack-lifecycle\n\n[![npm version](https://img.shields.io/npm/v/@atomist/sdm-pack-lifecycle.svg)](https://www.npmjs.com/package/@atomist/sdm-pack-lifecycle)\n[![atomist sdm goals](https://badge.atomist.com/T29E48P34/atomist/sdm-pack-lifecycle/0f0e2fa6-3377-4384-b70a-35bd62355d2f)](https://app.atomist.com/workspace/T29E48P34)\n\n## Extending Lifecycle\n\nTo extend lifecycle three different extension points are available:\n\n* `NodeRenderer` is concerned with rendering information as part of the lifecycle message\n* `ActionContributor` adds `Action` instances to a lifecycle message pointing to\n* `CommandHandlerRegistration` instances to add additional commands\n\nImplementations of the above can be registered wit the Lifecycle support by passing them\nas part of the `LifecycleOptions` to the `lifecycleSupport` extension pack.\n\n#### Modifying Lifecycle Message Content\n\nThe following example shows a [`CommitMessageWarningPushNodeRenderer`](https://github.com/atomist/sdm-pack-lifecycle/blob/master/test/sample/renderer.ts)\nthat adds an additional attachment to the push lifecycle to show violations against a commit message formatting policy:\n\n```typescript\n/**\n * NodeRenderer implementation that verifies the format of a commit message and\n * adds a Slack attachment showing all format warnings.\n */\nexport class CommitMessageWarningPushNodeRenderer extends AbstractIdentifiableContribution\n    implements SlackNodeRenderer\u003cPushToPushLifecycle.Push\u003e {\n\n    public static ID: string = \"commit_message\";\n\n    constructor() {\n        super(CommitMessageWarningPushNodeRenderer.ID);\n    }\n\n    public supports(node: PushToPushLifecycle.Push): boolean {\n        return !!node.after;\n    }\n\n    public async render(node: PushToPushLifecycle.Push,\n                        actions: Action[],\n                        msg: SlackMessage,\n                        rc: RendererContext): Promise\u003cSlackMessage\u003e {\n\n        if (await isDismissed(node, rc)) {\n            return msg;\n        }\n\n        const warnings: string[] = [];\n\n        const commitMsg = node.after.message;\n        const firstRow = commitMsg.split(\"\\n\")[0];\n\n        if (firstRow.charAt(0) !== firstRow.charAt(0).toUpperCase()) {\n            warnings.push(`Message doesn't start with an uppercase letter`);\n        }\n        if (firstRow.length \u003e 50) {\n            warnings.push(`First row is longer than 50 characters`);\n        }\n\n        if (warnings.length \u003e 0) {\n            const attachment: Attachment = {\n                author_icon: `https://images.atomist.com/rug/warning-yellow.png`,\n                author_name: \"Commit Message Format\",\n                text: `Commit message violates our format policy:\\n\\n${warnings.map(w =\u003e ` * ${w}`).join(\"\\n\")}`,\n                fallback: \"Commit Message Format\",\n                color: \"#D7B958\",\n                mrkdwn_in: [\"text\"],\n                actions,\n            };\n            msg.attachments.push(attachment);\n        }\n\n        return msg;\n    }\n\n}\n``` \n\nThe `supports` method gets called for each node of the lifecycle; e.g. the Push, all Commits and Tags etc in case of \npush lifecycle. If `support` returns `true` the render method will be invoked with the supported node.\n\nThe `render` method receives the `SlackMessage` that was created by previous `NodeRenderer` instances and can make any\ndesired modifications to the message content. Additionally all contributed `Action` instances are passed into `render` \nso that those can be placed into the message by the renderer.\n\n#### Adding Lifecycle Actions\n\nThe following code block shows an example of an `ActionContributor` that adds a button for a dismiss action to the push\nlifecycle. The code is available in [`CommitMessageWarningPushActionContributor`](https://github.com/atomist/sdm-pack-lifecycle/blob/master/test/sample/action.ts).\n\n```typescript\n/**\n * ActionContributor adding a button to dismiss the commit message warnings\n */\nexport class CommitMessageWarningPushActionContributor extends AbstractIdentifiableContribution\n    implements SlackActionContributor\u003cPushToPushLifecycle.Push\u003e {\n\n    constructor() {\n        super(\"dismiss_commit_message\");\n    }\n\n    public supports(node: any, rc: RendererContext): boolean {\n        return !!node.after \u0026\u0026 rc.rendererId === CommitMessageWarningPushNodeRenderer.ID;\n    }\n\n    public async buttonsFor(node: PushToPushLifecycle.Push,\n                            rc: RendererContext): Promise\u003cAction[]\u003e {\n\n        if (!(await isDismissed(node, rc))) {\n            return [\n                actionableButton(\n                    { text: \"Dismiss\" },\n                    DismissCommitMessageWarningCommand,\n                    {\n                        owner: node.repo.owner,\n                        repo: node.repo.name,\n                    }),\n            ];\n        }\n\n        return [];\n    }\n\n    public async menusFor(node: PushToPushLifecycle.Push,\n                          rc: RendererContext): Promise\u003cAction[]\u003e {\n        return [];\n    }\n}\n```\n\nSimilar to `NodeRenderer` instances, the `supports` method can be used to determine if a certain node is supported and\nif the action should be placed onto the content created by a particular `NodeRenderer`.\n\nThe two methods `buttonsFor` and `menuFor` are then called to create Slack button or menu `Action`s respectively.\n\n#### Configuring Lifecycle Extensions\n\n`NodeRenderer` and `ActionContributor` instances need to be registered with `lifecycleSupport` as follows:\n\n```typescript\n    const lifecycleOptions: LifecycleOptions = deepmerge(DefaultLifecycleRenderingOptions, {\n        push: {\n            chat: {\n                renderers: [() =\u003e [\n                    new CommitMessageWarningPushNodeRenderer(),\n                ]],\n                actions: [() =\u003e [\n                    new CommitMessageWarningPushActionContributor(),\n                ]],\n            },\n        },\n        commands: [\n            DismissCommitMessageWarningCommand,\n        ],\n    });\n\n    sdm.addExtensionPacks(lifecycleSupport(lifecycleOptions));\n```\n`DefaultLifecycleRenderingOptions` is a pre-defined configuration that contains all out of the box renderers and action\ncontributors that this pack contains. This serves as basis to add a new renderer and action contributor to the overall\nlfiecycle configuration. \n\nIn addition, this registers a `CommandHandlerRegistration` that implements the dismiss logic that is used to bind to a \nbutton in the sample `CommitMessageWarningPushActionContributor`.\n\n## Getting started\n\nSee the [Developer Quick Start][atomist-quick] to jump straight to\ncreating an SDM.\n\n[atomist-quick]: https://docs.atomist.com/quick-start/ (Atomist - Developer Quick Start)\n\n## Contributing\n\nContributions to this project from community members are encouraged\nand appreciated. Please review the [Contributing\nGuidelines](CONTRIBUTING.md) for more information. Also see the\n[Development](#development) section in this document.\n\n## Code of conduct\n\nThis project is governed by the [Code of\nConduct](CODE_OF_CONDUCT.md). You are expected to act in accordance\nwith this code by participating. Please report any unacceptable\nbehavior to code-of-conduct@atomist.com.\n\n## Documentation\n\nPlease see [docs.atomist.com][atomist-doc] for\n[developer][atomist-doc-sdm] documentation.\n\n[atomist-doc-sdm]: https://docs.atomist.com/developer/sdm/ (Atomist Documentation - SDM Developer)\n\n## Connect\n\nFollow [@atomist][atomist-twitter] and [The Composition][atomist-blog]\nblog related to SDM.\n\n[atomist-twitter]: https://twitter.com/atomist (Atomist on Twitter)\n[atomist-blog]: https://the-composition.com/ (The Composition - The Official Atomist Blog)\n\n## Support\n\nGeneral support questions should be discussed in the `#support`\nchannel in the [Atomist community Slack workspace][slack].\n\nIf you find a problem, please create an [issue][].\n\n[issue]: https://github.com/atomist-seeds/sdm-pack/issues\n\n## Development\n\nYou will need to install [Node.js][node] to build and test this\nproject.\n\n[node]: https://nodejs.org/ (Node.js)\n\n### Build and test\n\nInstall dependencies.\n\n```\n$ npm install\n```\n\nUse the `build` package script to compile, test, lint, and build the\ndocumentation.\n\n```\n$ npm run build\n```\n\n### Release\n\nReleases are handled via the [Atomist SDM][atomist-sdm].  Just press\nthe 'Approve' button in the Atomist dashboard or Slack.\n\n[atomist-sdm]: https://github.com/atomist/atomist-sdm (Atomist Software Delivery Machine)\n\n---\n\nCreated by [Atomist][atomist].\nNeed Help?  [Join our Slack workspace][slack].\n\n[atomist]: https://atomist.com/ (Atomist - How Teams Deliver Software)\n[slack]: https://join.atomist.com/ (Atomist Community Slack) \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomist%2Fsdm-pack-lifecycle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomist%2Fsdm-pack-lifecycle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomist%2Fsdm-pack-lifecycle/lists"}