{"id":21425835,"url":"https://github.com/battleroid/ngtca","last_synced_at":"2026-04-16T12:02:59.208Z","repository":{"id":53530257,"uuid":"240548973","full_name":"Battleroid/ngtca","owner":"Battleroid","description":"Never Go To Confluence Again","archived":false,"fork":false,"pushed_at":"2023-10-18T02:04:22.000Z","size":25,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-23T07:28:30.333Z","etag":null,"topics":["confluence","documentation","markdown"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Battleroid.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-14T16:13:33.000Z","updated_at":"2023-01-12T13:01:50.000Z","dependencies_parsed_at":"2024-01-15T20:51:55.201Z","dependency_job_id":"17a25dbf-2658-4f3a-9ec2-0d3ae8b64b16","html_url":"https://github.com/Battleroid/ngtca","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Battleroid%2Fngtca","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Battleroid%2Fngtca/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Battleroid%2Fngtca/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Battleroid%2Fngtca/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Battleroid","download_url":"https://codeload.github.com/Battleroid/ngtca/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243933437,"owners_count":20370986,"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":["confluence","documentation","markdown"],"created_at":"2024-11-22T21:38:16.812Z","updated_at":"2026-04-16T12:02:54.171Z","avatar_url":"https://github.com/Battleroid.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NGTCA\n\n**N**ever **G**o **T**o **C**onfluence **A**gain.\n\nThis should make adding and editing documentation less of a pain.\n\nIt's not without fault and has its own set of limitations. Generally you should use this with the assumption the documentation in Github would be the source of truth, what's in Confluence should be of a _\"good enough for me\"_ quality. My personal recommendation is to use this along with Jekyll to host a nice, pretty, easy to use site and then push what's required into Confluence if necessary. Then let people who want to use Confluence use that, while not sacrificing your sanity to use your own documentation.\n\n## Usage as a CLI\n\n```\nusage: ngtca [-h] [--conf-endpoint CONF_ENDPOINT] [--conf-user CONF_USER]\n             [--conf-pass CONF_PASS] [-l [LABELS [LABELS ...]]] [-d]\n             [--version]\n             path\n\npositional arguments:\n  path\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --conf-endpoint CONF_ENDPOINT\n                        confluence wiki endpoint (default:\n                        https://example.atlassian.net/wiki)\n  --conf-user CONF_USER\n                        confluence user (default: None)\n  --conf-pass CONF_PASS\n                        confluence pass/token (default: None)\n  -l [LABELS [LABELS ...]], --labels [LABELS [LABELS ...]]\n                        global labels applied to all pages (default: set())\n  -d, --debug           debug messages (default: False)\n  --version             show program's version number and exit\n```\n\nNGTCA can be used with a token from [id.atlassian.com](https://id.atlassian.com/manage/api-tokens). The following environment variables or CLI options need to be set:\n\n- `--conf-endpoint` or `CONFLUENCE_ENDPOINT`, defaults to `https://example.atlassian.net/wiki`\n- `--conf-user` or `CONFLUENCE_USER`, this can be the email address of the token's owner, e.g. `user@example.com`\n- `--conf-pass` or `CONFLUENCE_PASS`, this should be set to the token value\n\n## Prepping Documents\n\n### The Basics\n\nMinimal required frontmatter is a title, e.g. `title: My Documentation` is good enough, however this will post under the root of the space, it's preferred if you specify a parent page. Parents can be either a title or the ID number of the parent. AFAICT, the parent title does not need to be case sensitive. For example:\n\n```\n---\nc_title: My Super Page\nc_parent: Sample Team Directory\n---\n```\n\n### Extras\n\nOptionally, `c_space`, `c_toc` can be specified. Space by default is set to `IN`, the Ops documentation space. Setting `c_toc` to true will insert a Table of Contents macro at the beginning of your document when inserted into Confluence. For example:\n\n```\n---\nc_title: My Super Page\nc_parent: Sample Team Directory\nc_toc: true\nc_space: SOMETHING\n---\n```\n\n### Labels\n\nIf you need a particular label added to a page (or pages) you can just specify a list of labels in the frontmatter via `c_labels`. Extra spacing and non conforming labels will not be set (must be a-z or -). Upon publishing, any labels not part of the page's labels will be removed. For example:\n\n```\n---\nc_title: My Super Page\nc_labels: some-label, something-else, more_labels, i'm@not-a_good_labeldon\"tdothis\n---\n```\n\nIf you want to include a label(s) across all documents for a run just use `--labels`. Labels specified here will be merged with the page labels.\n\n### Ordering\n\nIf you require a specific page or set of pages to be made before others (to place documents under another to be made document) you can specify `c_order` in the frontmatter. It operates in an ascending manner, by default all documents receive an order of 0. Setting the order higher will push their publishing further down.\nSee [sample](sample/) for an example. The Sample page is created as one of the first, with a number of pages under it using it's title as the parent.\n\n### Example Usage\n\nSample usage on [ngtca_sample](ngtca_sample):\n\n```\n$ ngtca ../ngtca-sample -l repo-ops-ngtca-sample --debug\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:334  Debug on\n[2018-05-01 14:33:51] ngtca.ngtca [INFO    ]   ngtca.py:104  ../ngtca-sample is a directory, searching for markdown files recursively\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:93   Added page \u003cPage path:../ngtca-sample/docs/sample.md, title:NGTCA Examples (parent:Other)\u003e\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:93   Added page \u003cPage path:../ngtca-sample/docs/nope.md, title:I shouldn't exist (parent:9999999999999999999999999999999999999999)\u003e\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:93   Added page \u003cPage path:../ngtca-sample/docs/sample_id.md, title:Sample ID (parent:398360897)\u003e\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:93   Added page \u003cPage path:../ngtca-sample/docs/nested/hello.md, title:Sample Nested (parent:NGTCA Examples)\u003e\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:93   Added page \u003cPage path:../ngtca-sample/docs/other.md, title:Sample ToC (parent:NGTCA Examples)\u003e\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:88   Skipping \u003cPage path:../ngtca-sample/readme.md\u003e, no metadata or title\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:205  Publishing page 1/5: \u003cPage path:../ngtca-sample/docs/sample.md, title:NGTCA Examples (parent:Other)\u003e order: 0\n[2018-05-01 14:33:51] ngtca.ngtca [DEBUG   ]   ngtca.py:151  Updating \u003cPage path:../ngtca-sample/docs/sample.md, title:NGTCA Examples (parent:Other)\u003e\n[2018-05-01 14:33:52] ngtca.ngtca [DEBUG   ]   ngtca.py:179  Setting labels for \u003cPage path:../ngtca-sample/docs/sample.md, title:NGTCA Examples (parent:Other)\u003e to elasticsearch, ngtca, repo-ops-ngtca-sample\n[2018-05-01 14:33:53] ngtca.ngtca [DEBUG   ]   ngtca.py:205  Publishing page 2/5: \u003cPage path:../ngtca-sample/docs/nested/hello.md, title:Sample Nested (parent:NGTCA Examples)\u003e order: 0\n[2018-05-01 14:33:53] ngtca.ngtca [DEBUG   ]   ngtca.py:151  Updating \u003cPage path:../ngtca-sample/docs/nested/hello.md, title:Sample Nested (parent:NGTCA Examples)\u003e\n[2018-05-01 14:33:54] ngtca.ngtca [DEBUG   ]   ngtca.py:179  Setting labels for \u003cPage path:../ngtca-sample/docs/nested/hello.md, title:Sample Nested (parent:NGTCA Examples)\u003e to repo-ops-ngtca-sample\n[2018-05-01 14:33:54] ngtca.ngtca [DEBUG   ]   ngtca.py:205  Publishing page 3/5: \u003cPage path:../ngtca-sample/docs/other.md, title:Sample ToC (parent:NGTCA Examples)\u003e order: 10\n[2018-05-01 14:33:54] ngtca.ngtca [DEBUG   ]   ngtca.py:151  Updating \u003cPage path:../ngtca-sample/docs/other.md, title:Sample ToC (parent:NGTCA Examples)\u003e\n[2018-05-01 14:33:55] ngtca.ngtca [DEBUG   ]   ngtca.py:179  Setting labels for \u003cPage path:../ngtca-sample/docs/other.md, title:Sample ToC (parent:NGTCA Examples)\u003e to ngtca, repo-ops-ngtca-sample\n[2018-05-01 14:33:56] ngtca.ngtca [DEBUG   ]   ngtca.py:205  Publishing page 4/5: \u003cPage path:../ngtca-sample/docs/nope.md, title:I shouldn't exist (parent:9999999999999999999999999999999999999999)\u003e order: 20\n[2018-05-01 14:33:56] ngtca.ngtca [ERROR   ]   ngtca.py:213  \u003cPage path:../ngtca-sample/docs/nope.md, title:I shouldn't exist (parent:9999999999999999999999999999999999999999)\u003e 9999999999999999999999999999999999999999 is not a valid parent, skipping\n[2018-05-01 14:33:56] ngtca.ngtca [DEBUG   ]   ngtca.py:205  Publishing page 5/5: \u003cPage path:../ngtca-sample/docs/sample_id.md, title:Sample ID (parent:398360897)\u003e order: 20\n[2018-05-01 14:33:57] ngtca.ngtca [DEBUG   ]   ngtca.py:151  Updating \u003cPage path:../ngtca-sample/docs/sample_id.md, title:Sample ID (parent:398360897)\u003e\n[2018-05-01 14:33:57] ngtca.ngtca [DEBUG   ]   ngtca.py:179  Setting labels for \u003cPage path:../ngtca-sample/docs/sample_id.md, title:Sample ID (parent:398360897)\u003e to repo-ops-ngtca-sample\n```\n\n## Caveats \u0026 Notes\n\n### Updating Content\n\nUnfortunately, due to the wonkiness and ass-backwards nature of Confluence's API, there's no solid way to compare old with new content. It does not store the raw content, so there's no way to accurately do a diff between the two. So any update, will update all of it.\n\n### Confluence Markup\n\nWiki markup won't work here, most of standard markdown will work without issue. The only markup that has been changed is the fenced code block. It has been modified to use the code macro for syntax highlighting. If no language is specified then text is used for no highlighting.\n\nSome stuff like embedded image links and links to media (not text, binary) will be converted to the proper [XML markup](https://confluence.atlassian.com/doc/confluence-storage-format-790796544.html). It does this just by guessing the mimetype. That's it.\n\n### Removing Content\n\nUnfortunately, at this moment I can't think of a good (and safe) way to cleanup old documentation. I'd rather this be a _push_ only process. Where if you need a document within Confluence removed, you do it yourself as that is a process that is not often done. Creation and editing of pages is however something done frequently.\n\nBasically:\n\n- Create or update page? _Use NGTCA_\n- Delete or change parent page? _Go to Confluence_\n\n### Changing Parents\n\nDelete the old page within Confluence, make an update to trigger creating the page where it's desired. However, it might be easier to just reassign it in the frontmatter and within Confluence to keep the versioning.\n\n### Selecting Documents via Title/Parent\n\nDue to how annoying the Confluence API is, NGTCA finds existing documents by using an exact CQL match query.\n\nFor example, even if you have \"Sample\", \"Sample A\", \"Sample B\", and you set your doc's title to \"Sample\" it will _only_ look for and match the \"Sample\" document. This appears to be case sensitive. So \"Sample\" will not match \"sample\", but the two titles cannot conflict (technically a case insensitive exact search is possible, but I'm not sure yet how to do this via the API yet).\n\n### Documents with Matching Titles\n\nIf two documents share the same title, they will clobber and one of the two (likely whichever was found last) will be used. Titles are unique and used to identify the pages.\n\n### Relative Links\n\n~At this time, there's not a decent way to approach this. It may come down to it that the lexer/tokenizer that handles links will need to be mangled to call out to Confluence to find the appropriate document.~\n\n~This introduces a complex problem as ordering of documents might affect if pages are even available to reference.~\n\n~Relative links will work within Github pages, Jekyll, etc, but not within Confluence. So it's important to group your documents under a common parent to make things easy to find inside Confluence. At the end of the day however, the idea is to _NGTCA_ so for now I'm leaving it be.~\n\nThis should now work (at least within the same space for sure). Between spaces I'm not 100% sure, however, you can just use an absolute link anyway so that point may be moot.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbattleroid%2Fngtca","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbattleroid%2Fngtca","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbattleroid%2Fngtca/lists"}