Giter VIP home page Giter VIP logo

go-markdown2confluence's Introduction

markdown2confluence

Push markdown files to Confluence Cloud

Build Status

Installation

Download the latest release and add the binary in your local PATH

  • Linux

    curl -LO https://github.com/justmiles/go-markdown2confluence/releases/download/v3.4.6/go-markdown2confluence_3.4.6_linux_x86_64.tar.gz
    
    sudo tar -xzvf go-markdown2confluence_3.4.6_linux_x86_64.tar.gz -C /usr/local/bin/ markdown2confluence
  • OSX

    curl -LO https://github.com/justmiles/go-markdown2confluence/releases/download/v3.4.6/go-markdown2confluence_3.4.6_darwin_x86_64.tar.gz
    
    sudo tar -xzvf go-markdown2confluence_3.4.6_darwin_x86_64.tar.gz -C /usr/local/bin/ markdown2confluence
  • Windows

    Download the latest release and add to your system PATH

Use with Docker

docker run justmiles/markdown2confluence --version

Build using docker

docker run -v $PWD:/src -w /src goreleaser/goreleaser --snapshot --skip-publish --rm-dist

Environment Variables

For best practice we recommend you authenticate using an API token.

However, you may also use Personal Access Tokens, which may help if your company uses SSO.

  • CONFLUENCE_USERNAME - username for Confluence Cloud. When using API tokens set this to your full email.
  • CONFLUENCE_PASSWORD - API token or password for Confluence Cloud
  • CONFLUENCE_ENDPOINT - endpoint for Confluence Cloud, eg https://mycompanyname.atlassian.net/wiki
  • CONFLUENCE_ACCESS_TOKEN - Bearer access token to use (instead of API token)

Usage

Push markdown files to Confluence Cloud

Usage:
  markdown2confluence [flags]

Flags:
  -a, --access-token string   Confluence access-token. (Alternatively set CONFLUENCE_ACCESS_TOKEN environment variable)
  -c, --comment string        (Optional) Add comment to page
  -d, --debug                 Enable debug logging
  -e, --endpoint string       Confluence endpoint. (Alternatively set CONFLUENCE_ENDPOINT environment variable) (default "https://mydomain.atlassian.net/wiki")
  -x, --exclude strings       list of exclude file patterns (regex) for that will be applied on markdown file paths
  -w, --hardwraps             Render newlines as <br />
  -h, --help                  help for markdown2confluence
  -i, --insecuretls           Skip certificate validation. (e.g. for self-signed certificates)
  -m, --modified-since int    Only upload files that have modifed in the past n minutes
      --parent string         Optional parent page to nest content under
  -p, --password string       Confluence password. (Alternatively set CONFLUENCE_PASSWORD environment variable)
  -s, --space string          Space in which page should be created
  -t, --title string          Set the page title on upload (defaults to filename without extension)
      --use-document-title    Will use the Markdown document title (# Title) if available
  -u, --username string       Confluence username. (Alternatively set CONFLUENCE_USERNAME environment variable)
      --version               version for markdown2confluence

Examples

Upload a local directory of markdown files called markdown-files to Confluence.

markdown2confluence \
  --space 'MyTeamSpace' \
  markdown-files

Upload the same directory, but only those modified in the last 30 minutes. This is particurlarly useful for cron jobs/recurring one-way syncs.

markdown2confluence \
  --space 'MyTeamSpace' \
  --modified-since 30 \
  markdown-files

Upload a single file

markdown2confluence \
  --space 'MyTeamSpace' \
  markdown-files/test.md

Upload a directory of markdown files in space MyTeamSpace under the parent page API Docs

markdown2confluence \
  --space 'MyTeamSpace' \
  --parent 'API Docs' \
  markdown-files

Upload a directory of markdown files in space MyTeamSpace under a nested parent page Docs/API and exclude mardown files/directories that match .*generated.* or .*temp.md

markdown2confluence \
  --space 'MyTeamSpace' \
  --parent 'API/Docs' \
  --exclude '.*generated.*' \
  --exclude '.*temp.md' \
   markdown-files

Upload a directory of markdown files in space MyTeamSpace under the parent page API Docs and use the markdown document-title instead of the filname as document title (if available) in Confluence.

markdown2confluence \
  --space 'MyTeamSpace' \
  --parent 'API Docs' \
  --use-document-title \
   markdown-files

Enhancements

It is possible to insert Confluence macros using fenced code blocks. The "language" for this is CONFLUENCE-MACRO, exactly like that in all-caps. Here is an example for a ToC macro using all headlines starting at Level 2:

    # Title

    ```CONFLUENCE-MACRO
    name:toc
    schema-version:1
      minLevel:2
    ```

    ## Section 1

In general almost all macros should be possible. The general syntax is:

    ```CONFLUENCE-MACRO
    name:Name of Macro
    schema-version:Schema Version (use `1`)
      attribute:Value of Attribute
      parameter-name:Value of Parameter
      next-parameter:Value of Parameter
    ```

So a fully fledged macro could look like:

    ```CONFLUENCE-MACRO
    name:toc
    schema-version:1
      maxLevel:5
      minLevel:2
      exclude:Beispiel.*
      style:none
      type:flat
      separator:pipe
    ```

Which will translate to:

<ac:structured-macro ac:name="toc" ac:schema-version="1" >
  <ac:parameter ac:name="maxLevel">5</ac:parameter>
  <ac:parameter ac:name="minLevel">2</ac:parameter>
  <ac:parameter ac:name="exclude">Beispiel.*</ac:parameter>
  <ac:parameter ac:name="style">none</ac:parameter>
  <ac:parameter ac:name="type">flat</ac:parameter>
  <ac:parameter ac:name="separator">pipe</ac:parameter>
</ac:structured-macro>

go-markdown2confluence's People

Contributors

dweber019 avatar elijahgagne avatar iamideas avatar johnhart-s1 avatar justmiles avatar skeeve avatar sykmschmieder avatar thewolfnl avatar wiquanappd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

go-markdown2confluence's Issues

markdown2confluence doesn't work on OSX

Hi!

It's a very good tool, but i can't run it on the OSX (macOS Mojave 10.14.6).
The error is "/usr/local/bin/markdown2confluence: cannot execute binary file". On the virtual machine with Ubuntu Xenial i have no problem.

Can it be updated to work on OSX?

Unable to add attachment when using brand new accesstoken

See justmiles/go-confluence#3

When using the brandspanking new accesstoken functionality we are able to create pages on our corporate confluence using SSO. So that is great! However when we also have attachments on the page it fails with a 401 response statuscode.

Here is the debug output

DEBU[0000] GET https://confluence-url.com/rest/api/content/352026659/child/attachment?filename=DataModel.png  
DEBU[0000] Response Status Code: 200                    
DEBU[0000] Response Body: '{"results":[{"id":"352026661","type":"attachment","status":"current","title":"DataModel.png","metadata":{"mediaType":"image/png","labels":{"results":[],"start":0,"limit":200,"size":0,"_links":{"self":"https://confluence-test.topaas.ns.nl/rest/api/content/352026661/label"}},"_expandable":{"currentuser":"","properties":"","frontend":"","editorHtml":""}},"extensions":{"mediaType":"image/png","fileSize":104340,"comment":""},"_links":{"webui":"/display/GPLLS/leverschema-datamodel?preview=%2F352026659%2F352026661%2FDataModel.png","download":"/download/attachments/352026659/DataModel.png?version=1&modificationDate=1667228691590&api=v2","thumbnail":"/download/thumbnails/352026659/DataModel.png?api=v2","self":"https://confluence-test.topaas.ns.nl/rest/api/content/352026661"},"_expandable":{"container":"/rest/api/content/352026659","operations":"","children":"/rest/api/content/352026661/child","restrictions":"/rest/api/content/352026661/restriction/byOperation","history":"/rest/api/content/352026661/history","ancestors":"","body":"","version":"","descendants":"/rest/api/content/352026661/descendant","space":"/rest/api/space/GPLLS"}}],"start":0,"limit":50,"size":1,"_links":{"self":"https://confluence-test.topaas.ns.nl/rest/api/content/352026659/child/attachment?filename=DataModel.png","base":"https://confluence-url.com","context":""}}' 
DEBU[0000] POST https://confluence-url.com/rest/api/content/352026659/child/attachment/352026661/data 
DEBU[0000] Response Status Code: 401                    
DEBU[0000] Response Body: ''                            
[unexpected end of JSON input]

When I try the same using postman, it does work, so it is not a confluence rights issue.

Could it be the POST for the attachment data uses the requestWithFunc function from the confluence client? That only has basic auth at the moment...

See https://github.com/justmiles/go-confluence/blob/83494e1d603019bfab31d9d9f9ddfa2b210f575f/client.go#L116

The normal request function has logic for adding the access-token to the request, the requestWithFunc function does not.

Handling images/attachments?

Hello again, I'm running into this and I'm not sure if I'm doing something wrong or if this just isn't included.

I have a directory of markdown files exported from a (cough) popular wiki like tool. The export structure goes something like this:

- Home page
  - page1.md
  - page1 (folder)
     - image1.png
     - image2.png
     - childpage.md
     - childpage (folder)
       - childpageimage.png
   - page2.md
   [...] 

Is there a way to make sure these files get attached to the resulting Confluence page?

(If no, then further questions are moot :) )

nested readme file uploads not working

markdown2confluence --space 'MyTeamSpace' --parent 'API Docs' markdown-files

I am guessing this should upload all the nested md files present in the dir "markdown-files"? Am i correct.

handle error response and fail fast

currently, when the login fails for some reason, it seems the MarkDown parser is still called and consequently returns a followup error message because it cannot parse the real error response:

Unable to upload markdown file, test.md:
	Error checking for existing page: invalid character '<' looking for beginning of value

The real error is printed first, but not handled and the program tries to continue:

RRO[0000] Unable to unmarshal API response. Received: '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><status><status-code>401</status-code><message>Request rejected because issuer is either not authorized or not authorized to impersonate</message></status>'

The way the error is handled is a bit misleading and not very intuitive, as it hides the root cause and it looks as if the file contained a markup error.

Define an anchor

How to parameterize the Anchor confluence-macro?

If i define a confluence-marco like below it ignores the name "testanchor"

[click me](#testanchor) 

```CONFLUENCE-MACRO
name:anchor
  testanchor
``

--debug output:

<ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"7bf385fb-1d50-484a-a7b4-21e789ff3ffe\" />

About Confluence Macros

I haven't had the time to check all the macros listed on https://confluence.atlassian.com/doc/macros-139387.html but I think all of those having Macro body: none will work with my enhancement.

I started looking into another enhancement which would support some or all of the macros having Macro body: richt text like so:

    # This is an ugly test

    ```CONFLUENCE-MACRO
    name:panel
      borderColor:pink
      bgColor:green
      titleColor:red
      borderWidth:4
      titleBGColor:magenta
      borderStyle:dashed
      title:PanelTitle
    :rich-text-body
    ```

    Lorem ipsum dolor

    situs vilate inis et abanit

    ```CONFLUENCE-MACRO
    /rich-text-body
    ```

    # FIN

which would result in this Confluence Page:

<h1>This is an ugly test</h1>
<ac:structured-macro ac:name="panel" ac:schema-version="1" ac:macro-id="3f76f3e8-51a3-4233-94c9-2c70c322b5ce">
  <ac:parameter ac:name="borderColor">pink</ac:parameter>
  <ac:parameter ac:name="bgColor">green</ac:parameter>
  <ac:parameter ac:name="titleColor">red</ac:parameter>
  <ac:parameter ac:name="borderWidth">4</ac:parameter>
  <ac:parameter ac:name="titleBGColor">magenta</ac:parameter>
  <ac:parameter ac:name="borderStyle">dashed</ac:parameter>
  <ac:parameter ac:name="title">PanelTitle</ac:parameter>
  <ac:rich-text-body>
    <p>Lorem ipsum dolor</p>
    <p>situs vilate inis et abanit</p>
  </ac:rich-text-body>
</ac:structured-macro>
<h1>FIN</h1>

It feels even more ugly than my previous version ;)

Maybe we should discuss how to go forward from here?

Support of mermaid

Mermaid is very good for diagram drawings, but currently markwodn2confluence doesn't support it. As far as I known, there is goldmark-mermaid extension, that allows to compile mermaid markdown to SVG.
I even have tried using it to compile and upload SVG in this fork, but for some reason it doesn't work.

ExternalChangesException: Trying to access unreconciled content

This error is thrown when updating a page that is currently being edited. Per Atlassian docs:

Thrown when trying to make changes to a page outside an editing session (e.g. inline comments) and those changes are disallowed. That can happen when we are in limited mode (synchrony disabled) or after fallback if the page hasn't been reconciled yet with Synchrony

	Error updating content: com.atlassian.confluence.internal.synchrony.ExternalChangesException: Trying to access unreconciled content 999999999. Retry in a few moments

support API tokens

currently, you have to supply username and password for uploading pages.
It would be preferable to use API tokens here, as they can be managed per script and are safer to use, e..g can be revoked.

Race condition on uploading recursively?

I was able to work around the issue I'm describing by pulling the source, changing lib/markdown.go to change Parallelism to 1, and re-uploading.

I think there's therefore a race-condition within the bit of code that creates the nested structure.

I have a folder structure like

docs
├── adrs
│   ├── arbitrary-file-persistence
│   │   ├── 20200114-arbitrary-file-persistence.md
│   │   └── resources
│   │       ├── arbitrary-file-persistence-cronjob.png
│   │       └── arbitrary-file-persistence-daemonset.png
│   ├── configmanagement
│   │   ├── 20200106-kubernetes-config.md
│   │   ├── 20200115-vault-secret-injection.md
│   │   └── 20200116-kubernetes-namespacing.md
│   ├── dependencies
│   │   ├── 20200108_loggingpackage.md
│   │   ├── 20200109_websocketpackage.md
│   │   └── 20200113_clipackage.md
│   ├── logging
│   │   ├── 20191213-initial-logging-design.md
│   │   ├── 20200110-es-indexes.md
│   │   └── resources
│   │       └── initial-platform-logging.png
│   ├── mesh
│   │   ├── 20200115-service-mesh.md
│   │   └── 20200117-istio.md
│   ├── metrics
│   │   ├── 20191218-inital-metrics.md
│   │   └── resources
│   │       └── 20191218-initialdesign.png
│   ├── platform
│   │   ├── 20191203-initial-platform-iteration.md
│   │   └── resources
│   │       ├── containerised-runtime.png
│   │       └── old-platform-runtime.png
│   ├── template.md
│   └── workflow
│       └── local
│           └── 20191219-local-kubernetes.md
├── debt
│   ├── 20200114-k8s-client-go-version.md
│   ├── 20200115-ca-bundle-injection.md
│   ├── 20200115-istio-system-components.md
│   └── 20200115-kubernetes-secrets.md
└── guides
    ├── building-docker-containers.md
    ├── cluster-setup-steps.md
    ├── istio.md
    ├── logging.md
    └── separate-runtime-and-worker-pods.md

When I run markdown2confluence --endpoint https://my-account.atlassian.net/wiki --space SVP --username me --password secret --parent "Source controlled documentation" docs I get

Source controlled documentation/adrs/arbitrary-file-persistence/20200114-arbitrary-file-persistence: https://improbableio.atlassian.net/wiki/x/z4A6KQ
Source controlled documentation/adrs/configmanagement/20200115-vault-secret-injection: https://improbableio.atlassian.net/wiki/x/xQA8KQ
Source controlled documentation/adrs/configmanagement/20200116-kubernetes-namespacing: https://improbableio.atlassian.net/wiki/x/HwMBKQ
Source controlled documentation/adrs/dependencies/20200108_loggingpackage: https://improbableio.atlassian.net/wiki/x/4oA6KQ
Source controlled documentation/adrs/configmanagement/20200106-kubernetes-config: https://improbableio.atlassian.net/wiki/x/1gA8KQ
Source controlled documentation/adrs/dependencies/20200109_websocketpackage: https://improbableio.atlassian.net/wiki/x/qoA-KQ
Source controlled documentation/adrs/dependencies/20200113_clipackage: https://improbableio.atlassian.net/wiki/x/LQP_K
Source controlled documentation/adrs/mesh/20200117-istio: https://improbableio.atlassian.net/wiki/x/s4BAKQ
Source controlled documentation/adrs/mesh/20200115-service-mesh: https://improbableio.atlassian.net/wiki/x/6gA8KQ
Source controlled documentation/adrs/logging/20200110-es-indexes: https://improbableio.atlassian.net/wiki/x/fQBBKQ
Source controlled documentation/adrs/metrics/20191218-inital-metrics: https://improbableio.atlassian.net/wiki/x/MgMBKQ
Source controlled documentation/adrs/logging/20191213-initial-logging-design: https://improbableio.atlassian.net/wiki/x/3AA9KQ
Source controlled documentation/adrs/template: https://improbableio.atlassian.net/wiki/x/RYE8KQ
ERRO[0006] com.atlassian.confluence.api.service.exceptions.BadRequestException: A page with this title already exists: A page already exists with the title debt in the space with key SVP
Source controlled documentation/debt/20200115-istio-system-components:
Source controlled documentation/adrs/platform/20191203-initial-platform-iteration: https://improbableio.atlassian.net/wiki/x/5wfXK
Source controlled documentation/debt/20200114-k8s-client-go-version: https://improbableio.atlassian.net/wiki/x/SgMBKQ
Source controlled documentation/debt/20200115-kubernetes-secrets: https://improbableio.atlassian.net/wiki/x/qwA6KQ
Source controlled documentation/debt/20200115-ca-bundle-injection: https://improbableio.atlassian.net/wiki/x/VQMBKQ
Source controlled documentation/adrs/workflow/local/20191219-local-kubernetes: https://improbableio.atlassian.net/wiki/x/SwP_K
ERRO[0007] com.atlassian.confluence.api.service.exceptions.BadRequestException: A page with this title already exists: A page already exists with the title guides in the space with key SVP
Source controlled documentation/guides/cluster-setup-steps:
Source controlled documentation/guides/logging: https://improbableio.atlassian.net/wiki/x/XYL_K
Source controlled documentation/guides/building-docker-containers: https://improbableio.atlassian.net/wiki/x/y4A-KQ
Source controlled documentation/guides/istio: https://improbableio.atlassian.net/wiki/x/agMBKQ
Source controlled documentation/guides/separate-runtime-and-worker-pods: https://improbableio.atlassian.net/wiki/x/cAA_KQ

Unable to upload markdown file, docs/debt/20200115-istio-system-components.md:
	Error creating parent page docs/debt/20200115-istio-system-components.md for debt: com.atlassian.confluence.api.service.exceptions.BadRequestException: A page with this title already exists: A page already exists with the title debt in the space with key SVP

Unable to upload markdown file, docs/guides/cluster-setup-steps.md:
	Error creating parent page docs/guides/cluster-setup-steps.md for guides: com.atlassian.confluence.api.service.exceptions.BadRequestException: A page with this title already exists: A page already exists with the title guides in the space with key SVP

and a space structure that looks like
Screenshot 2020-01-27 at 15 11 06

Fails to build on macos

make
env GOOS=darwin GOARCH=amd64 go build -ldflags '-X "main.Version=2.1.0 (df35ce4 2bdc968f29 61f7c00e23 758006882e - 2019-06-27 14:45)"' -o build/2.1.0/markdown2confluence-2.1.0-darwin-amd64

github.com/justmiles/go-markdown2confluence/markdown2confluence

markdown2confluence/MarkdownFile.go:74:11: content.Ancestors undefined (type confluence.Content has no field or method Ancestors)
note: module requires Go 1.12make: *** [build] Error 2

Feature: set parent content via README.md

If the parent page does not exist, it gets created with default content. I propose that if a README.md file is present in a folder, then that gets used as the parent's content (whether it is being created or not). This would align with how GitHub and many other Git services display the readme file when you browse to the root of a folder. If no readme file is present, then the existing behavior is used.

What do you think? If you like the idea, but don't think you'd be able to implement it anytime soon, I'd be happy to take a stab at it and submit a PR.

support linked documents

Hi, thanks for the tool. At a first glance it looks promising and helpful.

I've got a structure like this in my project:

project_root/readme.md
project_root/documentation/do_this.md
project_root/documentation/do_that.md

I use the readme.md moreover to link to the subdocuments and use it primarily as an index or TOC file. From the subdocuments, I link back to the index or to other subdocuments.

First problem I encounter is, that the the links between the project root directory and subdirectories are not translated into confluence pages/subpages and therefore do not work.

I think, I could flatten the structure to put the readme.md into the documentation subdirectory of the source code and just use the project root readme.md to link to the documentation/readme.md. That might do it.

A different case would be to have links to (other) source code files in my markdown. It would be cool to have a possibility to change relative links to local files at least by absolute links to the current repository. Sure, I can do that directly in the markdown, but wouldn't it be better to have this in the tooling?

Thanks,
ferdy

Adding page with the same title breaks confluence page structure

Firstly I would like to say this is a great software and works perfectly saving the md files to confluence.

Unfortunately the way we are trying to structure our docs doesn't work with it.

We have multiple git repositories which have a README.md file and we are trying to structure it like this:
(Confluence Space)/(Service Name)/(README.md file)

For example:

  • Architecture/module-transfer/technical
  • Architecture/module-crypt/technical

The individual services will run the following commands:
markdown2confluence --space 'Architecture' --parent 'module-transfer' -t 'technical' ./README.md
markdown2confluence --space 'Architecture' --parent 'module-crypt' -t 'technical' ./README.md

Existing behaviour:
module-transfer saves the README.md as a page on confluence under Architecture/module-transfer/technical.
module-crypt saves the README.md as a page on confluence under Architecture/module-crypt/technical.
The page Architecture/module-transfer/technical is being replaced by Architecture/module-crypt/technical and disappears.

I hope it explains what is happening. I think the problem is that the parent is not being treated as part of the page and only the page titled 'technical' is fetched and updated.

The only workaround I found is to give each page a unique name.

Regards

stale data

I constantly get Error updating content: Attempted to update stale data. Try again. is a way to ignore stale data and upload whatever the user wants irrespective of the page being stale or fresh.

How can I find the endpoints?

Hil Miles.

I'm struggling to find the correct endpoint to update/upload a page. Any hints where to get that information on atlassian?

Include Image

Hello,

we markdown2confluence appreciate "markdown2confluence" very much. As we use Github for user documentation as well there are lots of images inside. Github Markdown allows to include images.

Markdown Image Syntax:
![ALTTEXT] {PATH}{width="WIDTH"}

These image links should be rendered in conflence to
<img src="URL" width="WIDTH" alt="ALTTEXT"/>{:width=&quot;640px&quot;}</p>

PATH may be a relative path to the page. So the PATH has to be mapped to the image's full URL.

Thanks and Best Regards

Stefan

Can't "make" on MacOS

4797 > make
env GOOS=darwin  GOARCH=amd64 go build -ldflags '-X "main.Version=2.1.0 (e9a50a812c 55da1196c0 94fe68e7ff 775c34ebf1 - 2019-11-15 09:48)"' -o build/2.1.0/markdown2confluence-2.1.0-darwin-amd64
go: github.com/justmiles/[email protected]: invalid pseudo-version: revision is shorter than canonical (8dad74c66d4d)
make: *** [build] Error 1

Support of Action item (task)

Is there support for action items (tasks) or is this planned?
In Confluence web an action item is created by typing [] followed by the text and optionally tagging an assignee using @Person and setting a due date using //Date.

Markdown could look similar to:
[ ] Task text @Person //2022-11-02
I tried these variants as well:
[] Task text (no space between [ and ]
- [ ] Task text (bullet point and space as suggest here: Markdown Checkbox

Confluence generates this XML

<ac:task-list>
<ac:task>
<ac:task-id>1</ac:task-id>
<ac:task-status>incomplete</ac:task-status>
<ac:task-body><span class="placeholder-inline-tasks">Task text <ac:link><ri:user ri:account-id="1df8763daa10476da25e461b" /></ac:link>  <time datetime="2022-11-02" /> </span></ac:task-body>
</ac:task>
</ac:task-list>

Is macro still working ?

Hi there,

Using:

$ markdown2confluence --version
markdown2confluence 3.1.2

I tried the example snipets for ToC from the README:

   ```CONFLUENCE-MACRO
    name:toc
      minLevel:2
    ```

It is not rendered in Confluence cloud.
Is it still working or did I miss something ?

Add option to set labels

It's possible to add an option for page tags?

I would really appreciate to do smth. lilke
--tags "api, public, reference"

Error with Bearer token

Hi,
I want to communicate with a self hosted confluence server "https://confluence.xxx.xxx.com" with a token and I get the same error as #7 (Basic Authentication Failure - Reason : AUTHENTICATION_DENIED).
Here is the command I run:
markdown2confluence -e 'https://confluence.xxx.xxx.com' -u '[email protected]' -p 'token' -s 'SPACE' --use-document-title test-markdown.md
I don't understand the reason why it fails whereas the command below works:

curl --request POST \
  --url 'https://confluence.xxx.xxx.com/rest/api/content' \
  --header 'Authorization: Bearer token' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "title": "My markdown page",
    "type": "page",
    "space": {
      "key": "SPACE"
    },
    "status": "current",
    "ancestors": [
      {
        "id": "312707572"
      }
    ],
    "body": {
      "storage": {
        "value": "This is a test page",
        "representation": "wiki"
      }
    },
    "metadata": {
      "properties":{
        "editor": {
          "value": "v2"
        }
      }
    }
  }'

As you can see I used the Bearer not Basic auth mode.
Related to #52 as well

"Unknown flag: --comment"

Howdy, working through a large import and I'd love to use the comment flag. However, I'm seeing unknown flag: --comment and unknown shorthand flag: 'c' in -c when I try to use it. It also doesn't appear in the --help text.

This is 3.3.1, so wondering if this commit got missed?

A page containing a % will be blank

When creating a simple page containing anywhere a % it will be completely blank in confluence

For example if markdown page contains :

# Test

Test page is 100% blank now...

Then result will be an empty page in confluence, when running in debug mode the content is also empty :

---- RENDERED CONTENT START ---------------------------------

---- RENDERED CONTENT END -----------------------------------

Escaping the % will provide the same result

Tested using docker version "markdown2confluence v3.3.0"

Using confluence cloud, failing first test, getting 401

Hi,
I have now tried to get this working for a while, without success.

I am trying: To create a test article in my own personal space on the confluence site we use.
Using debug flag, I see that: It fails on the first request it makes. Using curl, that same request works.

debug log:

$ markdown2confluence --debug --space '~174922101'   test.md                                                          test.md
---- RENDERED CONTENT START ---------------------------------
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>This is my test article.</p>
<p>username = &quot;[email protected]&quot;</p>

---- RENDERED CONTENT END -----------------------------------
time="2021-12-15T16:39:02+01:00" level=debug msg="GET https://<OURHOST>.atlassian.net/wiki/rest/api/content?expand=version%2Cbody.storage&limit=1&spaceKey=~174922101&title=test&type=page "
time="2021-12-15T16:39:02+01:00" level=debug msg="Response Status Code: 401"
time="2021-12-15T16:39:02+01:00" level=debug msg="Response Body: 'Basic authentication with passwords is deprecated.  For more information, see: https://confluence.atlassian.com/cloud/deprecation-of-basic-authentication-with-passwords-for-jira-and-confluence-apis-972355348.html\n'"
time="2021-12-15T16:39:02+01:00" level=error msg="Unable to unmarshal API response. Received: 'Basic authentication with passwords is deprecated.  For more information, see: https://confluence.atlassian.com/cloud/deprecation-of-basic-authentication-with-passwords-for-jira-and-confluence-apis-972355348.html\n'"
test:

Unable to upload markdown file, test.md:
        Error checking for existing page: invalid character 'B' looking for beginning of value
  • Notice the basic authentication message that confluence sends. Notice how it does not handle the HTTP error, but attempts to use the message in the body as the page content. :-)

Same query, successful using curl:

curl -D- \
-H "Authorization: Basic <MY-API-TOKEN> \
"https://<OURHOST>.atlassian.net/wiki/rest/api/content?expand=version%2Cbody.storage&limit=1&spaceKey=~174922101&title=test&type=page"
  • curl gets this response:
HTTP/2 200
server: AtlassianProxy/1.19.3.1
vary: Accept-Encoding
cache-control: no-cache, no-store, must-revalidate
content-type: application/json
strict-transport-security: max-age=315360000; includeSubDomains; preload
date: Wed, 15 Dec 2021 16:31:55 GMT
atl-traceid: 12fdf94d2827d347
expires: Thu, 01 Jan 1970 00:00:00 GMT
x-xss-protection: 1; mode=block
x-envoy-upstream-service-time: 44
x-content-type-options: nosniff
atl-confluence-via: h:confluence-prod-eu-4-3.prod.atl-paas.net
expect-ct: report-uri="https://web-security-reports.services.atlassian.com/expect-ct-report/global-proxy", enforce, max-age=86400

{"results":[],"start":0,"limit":1,"size":0,"_links":{"base":"https://i-p-e-x.atlassian.net/wiki","context":"/wiki","self":"https://i-p-e-x.atlassian.net/wiki/rest/api/content?spaceKey=~174922101&expand=version%2Cbody.storage&title=test&type=page"}}

The page does not exist, as the confluence response shows. But curl gets a response successfully.

Any tips or pointers?
Anything I can try to narrow the issue or something?

Possible to remove pages from the wiki where they have been deleted from disk?

Confluence doesn't expose a recursive-delete to regular users (of which I am one).

I want to be able to publish from the root of my repository's master branch, on merge to master, and not need to care about pages that have been deleted being removed (or, deleted+created; i.e. moved/renamed).

I've tried to think through the conditions and implications below. Would it be possible to have markdown2confluence handle:

  • page has been deleted
    • at a leaf node; delete it
    • at an intermediate node, when a page with children is deleted, the children are elevated to the position of the parent page. So I'd thought:
      • if the directory tree has been deleted - delete from the leaves upward
      • if the page has been deleted but the directory has not, the auto-generated-index page must remain behind but have the down-level node be removed
  • page has been renamed
    • at a leaf node; rename the page (which I assume keeps its edit-history)
    • at an intermediate node - I think there's no difference between leaf and intermediate here?
      • page: rename the node
      • directory: rename the node

Textflow incorrect?

If I'm not mistaken, one should keep lines in markdown files short (See https://github.com/markdownlint/markdownlint/blob/master/docs/RULES.md#md013---line-length)

Paragraphs are denoted by an empty line.

But when I upload my markdown file I see <br /> being inserted for each line end.

Am I doing something wrong?

Source

Im neuen XXXX sollen, unter anderem Daten von Partnern erfasst werden, wie
z.B. Absprung Raten von deren Kunden.
Die Daten können über verschiedene Wege, z.B. per sftp Upload auf unseren
Server zu uns gelangen.

Generated code

<p>Im neuen XXXX sollen, unter anderem Daten von Partnern erfasst werden, wie<br />
z.B. Absprung Raten von deren Kunden.<br />
Die Daten können über verschiedene Wege, z.B. per sftp Upload auf unseren<br />
Server zu uns gelangen.</p>

The <br />shouldn't be there at all.

Confluence pages created are in the old style.

Hi,

I really admire the effort put into the tool!

However what I've noticed is; when pages are created they are in the old style of editor.
There is this which describes the fix.

Unfortunately go is not a language which I've used much and it has been months ago when i was looking into this for the first time.

downloading the source and then doing it from so i can test some tweaks is something i just can't get working....
I would have expected that calling it like this:
go run ..\go-markdown2confluence\main.go -u '{email}' -p '{token}' -s '{space}' -e '{site}/wiki/home' -t '{title}' README.md
Would have worked.

but it results in:
Unable to upload markdown file, README.md: Error checking for existing page: invalid character '<' looking for beginning of value exit status 1

Because i assume the fix can be done by altering the 'content struct' in content.go with something like this:

// Metadata struct { // Properties struct { // Editor struct { // Key stringjson:"key,omitempty"// Value stringjson:"value,omitempty"// }json:"editor,omitempty"// }json:"properties,omitempty"// }json:"metadata,omitempty"

and then updating the file.go like

// bp.Metadata.Properties.Editor.Key = "editor"
// bp.Metadata.Properties.Editor.Value = "v2"

Would it be possible to add a command line parameter that can be used as --ceditor 'v2' ?

Many thanks in advance for reading this through!

Error while rendering confluence macros

Hello!

I have been trying to insert Confluence macro with the builtin support of markdown2confluence.

Having the markdown file I attached inside test.zip

I do:

markdown2confluence --space mySpace --username myUsename --password myPassword --endpoint myWikiEndpoint test.md

The command finishes successfully (exit code 0) but when I go to the generated page I see this:

image

If I check the generated confluence source code, I can find the following:

<h1>Title</h1>
<ac:structured-macro ac:macro-id="566545cd-7ssf-4sssf6-593-8985246769ss" ac:name="code" ac:schema-version="1">
  <ac:parameter ac:name="language">CONFLUENCE-MACRO</ac:parameter>
  <ac:parameter ac:name="theme">Confluence</ac:parameter>
  <ac:parameter ac:name="linenumbers">true</ac:parameter>
  <ac:plain-text-body><![CDATA[ name:toc
  minLevel:2
 ]]></ac:plain-text-body>
</ac:structured-macro>
<h2>Section 1</h2>

I am using markdown2confluence 3.1.2 and confluence 7.7.4

If you point me where the problem is, maybe I can even resolve and place a pull request

Apart from this issue, I must say, we're getting a lot of value from this tool, and we thank you @justmiles very much for developing it!

Image upload capability needed

Unfortunately it is not possible to upload markdown with image references:

Error creating page: Error parsing xhtml: Unexpected close tag

; expected

Subfolder uploaded to wrong location

I have a directory structure that looks like this (locally)

.
├── glossary.md
├── kickoff.md
├── services
│   └── service1
│       ├── cli-profiles.md
│       └── config.md
├── user-guides
│   ├── guid2.pdf
│   └── guid1.pdf
└── work-log
    └── foo.md

I upload with the tool

markdown2confluence --space 'SPACE' --parent 'PARENT-NAME' .

However, the space already appears to have a page called "service1". my markdown files are attached and uploaded there, rather than under the intended parent PARENT-NAME

support path for creating pages

currently, pages can only be created in a specific space, but you cannot specify a path (root page) where to put uploaded files. This would be very useful.

write pages with wide mode

In the confluence UI you have a button to make tables or the whole page wider. Is there a possibility to do this?

If not, maybe there could be a parameter such as --use-available-width.

EDIT A workaround is ofc to create the page and change it manually, this seems to not get overwritten

Nil pointer dereference

Hi, thanks for making this!

I was trying it out and got a segmentation violation, I'm including the whole output here if that helps. I'll try to debug it, but if this is a known issue or there's a problem with the way I'm using this tool, let me know!

:) confluence-experiment % docker run -v ~/Projects/confluence-experiment/go-markdown2-confluence/:/tmp justmiles/markdown2confluence -e "http://localhost:8090/display/TAS/" --space "TAS" --username "admin" --password "foo" --parent "1-Projects" /tmp

localhost:8090/display/TAS/" --space "TAS" --username "admin" --password "foo" --parent "1-Projects" /tmp
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x6de8b9]

goroutine 1 [running]:
github.com/justmiles/go-confluence.(*Client).request(0xc00022c140, 0x94ace6, 0x3, 0x9520bb, 0x11, 0xc00020c540, 0x3d, 0x0, 0x0, 0x0, ...)
	/go/src/vendor/github.com/justmiles/go-confluence/client.go:52 +0x489
github.com/justmiles/go-confluence.(*Client).GetContent(0xc00022c140, 0xc00001e240, 0x7ffc01a9ef74, 0xa, 0xd6cf80, 0x0, 0xc00025bca0)
	/go/src/vendor/github.com/justmiles/go-confluence/content.go:23 +0x10c
github.com/justmiles/go-markdown2confluence/lib.(*MarkdownFile).FindOrCreateAncestor(0xc00033fb58, 0xd41580, 0xc00022c140, 0x0, 0x0, 0x7ffc01a9ef74, 0xa, 0xc00033f960, 0x45f240, 0xc00033f9a8, ...)
	/go/src/lib/file.go:167 +0x138
github.com/justmiles/go-markdown2confluence/lib.(*MarkdownFile).FindOrCreateAncestors(0xc00033fb58, 0xd41580, 0xd41580, 0xc0001e7800, 0xc00000e118, 0xc000226ce0)
	/go/src/lib/file.go:140 +0xab
github.com/justmiles/go-markdown2confluence/lib.(*Markdown2Confluence).Run(0xd41580, 0x0, 0x0, 0x0)
	/go/src/lib/markdown.go:217 +0x44d
github.com/justmiles/go-markdown2confluence/cmd.glob..func1(0xd3a5e0, 0xc00011a370, 0x1, 0xb)
	/go/src/cmd/root.go:45 +0xf7
github.com/spf13/cobra.(*Command).execute(0xd3a5e0, 0xc00001e0d0, 0xb, 0xb, 0xd3a5e0, 0xc00001e0d0)
	/go/src/vendor/github.com/spf13/cobra/command.go:766 +0x29d
github.com/spf13/cobra.(*Command).ExecuteC(0xd3a5e0, 0x45, 0xc00033ff48, 0x441f4a)
	/go/src/vendor/github.com/spf13/cobra/command.go:850 +0x2fb
github.com/spf13/cobra.(*Command).Execute(...)
	/go/src/vendor/github.com/spf13/cobra/command.go:800
github.com/justmiles/go-markdown2confluence/cmd.Execute(0xa1c1e8, 0x6)
	/go/src/cmd/root.go:62 +0x8a
main.main()
	/go/src/main.go:11 +0x39

Possibility of adding header/footer to wiki pages to set expectations of readers?

I'd like to use this tool to publish documentation from source-control, via a cronjob / CI.

I'd therefore like to restrict wiki-editing of the content, which I think I can do via confluence permissions.

I'd like to set expectations for the people who read the docs via the confluence wiki:

  • I'd like to make it clear where the documentation comes from, so that they know where to make any edits - I was thinking a link to my source control and a little prose inside a callout
    • I'd like to add some metadata to the page in a callout that says which version control reference the page was published from
  • I'd like to warn people that comments will not persist (I just made a comment on a published page, and it was resolved after I republished (I did not change the markdown's content before republish))
    • unless there's a way to keep them
      • but this is definitely not a problem for me personally since we do doc-discussions inside pull requests and slack really

How to handle links properly

Hi, thanks for the tool. At a first glance it looks promising and helpful.

I've got a structure like this in my project:

project_root/readme.md
project_root/documentation/do_this.md
project_root/documentation/do_that.md

I use the readme.md moreover to link to the subdocuments and use it primarily as an index or TOC file. From the subdocuments, I link back to the index or to other subdocuments.

First problem I encounter is, that the the links between the project root directory and subdirectories are not translated into confluence pages/subpages and therefore do not work.

I think, I could flatten the structure to put the readme.md into the documentation subdirectory of the source code and just use the project root readme.md to link to the documentation/readme.md. That might do it.

A different case would be to have links to (other) source code files in my markdown. It would be cool to have a possibility to change relative links to local files at least by absolute links to the current repository. Sure, I can do that directly in the markdown, but wouldn't it be better to have this in the tooling?

Thanks,
ferdy

javax.persistence.OptimisticLockException when uploading document with images

I'm encountering an interesting issue that I can only consistently reproduce in Bitbucket Pipelines. Any time I add or change an image link, the markdown2confluence push of that document will fail on the first try like so

time="2023-02-28T16:33:31Z" level=debug msg="POST <redacted>/child/attachment"
time="2023-02-28T16:33:32Z" level=debug msg="Response Status Code: 500"
time="2023-02-28T16:33:32Z" level=debug msg="Response Body: '{\"statusCode\":500,\"message\":\"javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.atlassian.confluence.pages.Attachment#4362829904]\"}'"
time="2023-02-28T16:33:32Z" level=error msg="javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.atlassian.confluence.pages.Attachment#4362829904]"
[javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.atlassian.confluence.pages.Attachment#4362829904]]
GCP pgbouncer Deployment: <redacted>
Unable to upload markdown file Home/GCP pgbouncer [Deployment.md](http://deployment.md/): 
	javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.atlassian.confluence.pages.Attachment#4362829904]

However, the markdown2confluence import will work successfully if I retry the pipeline, so it seems to be related to quick subsequent modifications to the page. Also, if I simply try to push this up from my local workstation, I get no such issues, which is also interesting.

I don't really suspect it's an issue with this application, but maybe there's a way to handle this and retry?

Support Personal Access Token.

My current task is to upload some markdown files to a confluence server. I tried this project, and it almost worked out of the box. Except I need to use PAT instead of basic authentication. For now, I just replaced the code in the client as a PoC.

PAT

Handle invalid URLs

Hi Miles,

I also faced the same issue, but might have found the issue.
While executing your code in MacOS for confluence DC with debug mode I could see that while executing the GET API there is a space between the "Base URL" i.e technology-wiki and "/rest/api/content?...." which might be causing the receive a nil pointer.

DEBU[0000] GET https://technology-wiki /rest/api/content?limit=1&spaceKey=TGM%C2%A0&title=%E2%80%98Home%E2%80%99%C2%A0&type=page
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x12af5d8]

goroutine 1 [running]:
github.com/justmiles/go-confluence.(*Client).request(0xc00025e040, 0x1507586, 0x3, 0x150e78f, 0x11, 0xc0000e0400, 0x47, 0x0, 0x0, 0x0, ...)
/home/justmiles/go/pkg/mod/github.com/justmiles/[email protected]/client.go:52 +0x478
github.com/justmiles/go-confluence.(*Client).GetContent(0xc00025e040, 0xc000110180, 0x1511fbe, 0x18, 0xc00033f598, 0x1, 0x1)
/home/justmiles/go/pkg/mod/github.com/justmiles/[email protected]/content.go:23 +0x10c
github.com/justmiles/go-markdown2confluence/lib.(*MarkdownFile).FindOrCreateAncestor(0xc00033fb98, 0x180ffc0, 0xc00025e040, 0x0, 0x0, 0x7ff7bfeffc0c, 0xc, 0xc00033f9a0, 0x1063de0, 0xc00033f9e8, ...)
/home/justmiles/workspaces/justmiles/go-markdown2confluence/lib/file.go:167 +0x145
github.com/justmiles/go-markdown2confluence/lib.(*MarkdownFile).FindOrCreateAncestors(0xc00033fb98, 0x180ffc0, 0x180ffc0, 0xc0001b17d0, 0xc0000ba110, 0xc0000a7890)
/home/justmiles/workspaces/justmiles/go-markdown2confluence/lib/file.go:140 +0xab
github.com/justmiles/go-markdown2confluence/lib.(*Markdown2Confluence).Run(0x180ffc0, 0x0, 0x0, 0x0)
/home/justmiles/workspaces/justmiles/go-markdown2confluence/lib/markdown.go:248 +0x415
github.com/justmiles/go-markdown2confluence/cmd.glob..func1(0x18091a0, 0xc0001100c0, 0x1, 0xc)
/home/justmiles/workspaces/justmiles/go-markdown2confluence/cmd/root.go:46 +0x10d
github.com/spf13/cobra.(*Command).execute(0x18091a0, 0xc00009ab70, 0xc, 0xc, 0x18091a0, 0xc00009ab70)
/home/justmiles/go/pkg/mod/github.com/spf13/[email protected]/command.go:766 +0x2c2
github.com/spf13/cobra.(*Command).ExecuteC(0x18091a0, 0xc00008c000, 0xc00005e748, 0x18105e0)
/home/justmiles/go/pkg/mod/github.com/spf13/[email protected]/command.go:850 +0x30b
github.com/spf13/cobra.(*Command).Execute(...)
/home/justmiles/go/pkg/mod/github.com/spf13/[email protected]/command.go:800
github.com/justmiles/go-markdown2confluence/cmd.Execute(0x15bf89c, 0x5)
/home/justmiles/workspaces/justmiles/go-markdown2confluence/cmd/root.go:63 +0x8f
main.main()
/home/justmiles/workspaces/justmiles/go-markdown2confluence/main.go:11 +0x39

Please correct me if Im wrong here

Handle spaces in parent page names

Seems like spaces in parent page aren't handled.

When I pass in --parent 'Acceptance Tests' and have debug logging on, I see a search request being made with the space in it, and the parent page is not found. Then the parent is created with a POST, which fails since the page already exists.

When I pass in --parent 'Acceptance+Test' to try the way Confuence handles this, I see a search request being made with that exact string, which is not found and a new Parent page is made with the plus sign in it.

I'm now using a parent page without any spaces to get it to work. Would be great if I could use a 'normal' name to make this more useful for the user.

Old golang version in Dockerfile

FROM golang:1.14 as builder

I suggest that the version designation be 1.17 or higher.

That feature was added in 1.17.
https://go.dev/doc/go1.17

$ docker build .

...etc...

Step 6/12 : RUN CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -o markdown2confluence -ldflags "-s -w -X main.version=${VERSION}"
 ---> Running in 707d69576cf5
# golang.org/x/sys/unix
vendor/golang.org/x/sys/unix/syscall.go:83:16: undefined: unsafe.Slice
vendor/golang.org/x/sys/unix/syscall_linux.go:2255:9: undefined: unsafe.Slice
vendor/golang.org/x/sys/unix/syscall_unix.go:118:7: undefined: unsafe.Slice
vendor/golang.org/x/sys/unix/sysvshm_unix.go:33:7: undefined: unsafe.Slice

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.