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
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ GIT ?= git
REUSE ?= reuse
RM ?= rm
INSTALL ?= install
NPM ?= npm
SASS ?= ./node_modules/.bin/sass
STYLELINT ?= ./node_modules/.bin/stylelint
SCDOC ?= scdoc

REQUIRED_TOOLS := $(GO) $(GIT) $(SASS) $(SCDOC)
REQUIRED_TOOLS := $(GO) $(GIT) $(SASS) $(SCDOC) $(NPM)
GO_MIN_VERSION := 1.24

GOBUILD_FLAGS := -trimpath \
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ First install the dependencies:

- Go 1.24 or above.
- make.
- npm.
- [scdoc](https://git.sr.ht/~sircmpwn/scdoc).

Clone the repository, switch to the latest stable tag, then compile, and
Expand All @@ -43,6 +44,7 @@ install:
git clone 'https://github.com/cipherdothost/pkgdex.git'
cd 'pkgdex'
git checkout 'v1.0.0'
npm install
make
sudo make install
```
Expand All @@ -56,7 +58,8 @@ sudo make install
## Contributing

Anyone can help make **pkgdex** better. Check out [the contribution
guidelines](CONTRIBUTING.md) for more information.
guidelines](CONTRIBUTING.md) and [the development
instructions](docs/development.md) for more information.

---

Expand Down
1 change: 1 addition & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ path = [
"LICENSE-3rdparty.csv",
"config/apparmor/usr.local.bin.pkgdexctl",
"config/config.example.json",
"config/dev-config.example.json",
"config/nginx/pkg.example.com",
"config/systemd/pkgdex.service",
"internal/config/testdata/*.json",
Expand Down
61 changes: 61 additions & 0 deletions config/dev-config.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"service": {
"name": "Pkgdex",
"description": "A curated index of Go packages. Engineered by Cipher Host.",
"contact": "support@example.com",
"homepage": "https://localhost:8080",
"baseURL": "localhost:8080",
"packagesPerPage": 2,
"seo": {
"title": "Cipher Host's Go Package Index",
"description": "A curated collection of professional-grade tools to enhance your Go projects. Browse and discover Cipher Host's carefully engineered Go packages and modules."
}
},
"server": {
"address": ":8080",
"pid": "/path/to/pkgdex/repository/clone/.dev/pkgdex.pid",
"readTimeout": "5s",
"writeTimeout": "10s",
"idleTimeout": "30s"
},
"database": {
"path": "/path/to/pkgdex/repository/clone/.dev/pkgdex.db",
"indexPath": "/path/to/pkgdex/repository/clone/.dev/index"
},
"packages": [
{
"name": "credential-go",
"description": "A simple interface for retrieving secrets from systemd's credential management system.",
"version": "1.0.0",
"branch": "trunk",
"repository": "https://git.sr.ht/~jamesponddotco/credential-go",
"license": "MIT",
"usage": "<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"line\"><span class=\"ln\" id=\"usage-line-1\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-1\"> 1</a></span><span class=\"cl\"><span class=\"kn\">package</span> <span class=\"nx\">main</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-2\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-2\"> 2</a></span><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-3\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-3\"> 3</a></span><span class=\"cl\"><span class=\"kn\">import</span> <span class=\"p\">(</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-4\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-4\"> 4</a></span><span class=\"cl\">\t<span class=\"s\">&#34;fmt&#34;</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-5\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-5\"> 5</a></span><span class=\"cl\">\t<span class=\"s\">&#34;log&#34;</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-6\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-6\"> 6</a></span><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-7\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-7\"> 7</a></span><span class=\"cl\">\t<span class=\"s\">&#34;git.sr.ht/~jamesponddotco/credential-go&#34;</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-8\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-8\"> 8</a></span><span class=\"cl\"><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-9\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-9\"> 9</a></span><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-10\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-10\">10</a></span><span class=\"cl\"><span class=\"kd\">func</span> <span class=\"nf\">main</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-11\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-11\">11</a></span><span class=\"cl\">\t<span class=\"c1\">// Open the credential store with your application&#39;s name as the prefix.\n</span></span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-12\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-12\">12</a></span><span class=\"cl\"><span class=\"c1\"></span>\t<span class=\"nx\">store</span><span class=\"p\">,</span> <span class=\"nx\">err</span> <span class=\"o\">:=</span> <span class=\"nx\">credential</span><span class=\"p\">.</span><span class=\"nf\">Open</span><span class=\"p\">(</span><span class=\"s\">&#34;myapp&#34;</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-13\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-13\">13</a></span><span class=\"cl\">\t<span class=\"k\">if</span> <span class=\"nx\">err</span> <span class=\"o\">!=</span> <span class=\"kc\">nil</span> <span class=\"p\">{</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-14\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-14\">14</a></span><span class=\"cl\">\t\t<span class=\"nx\">log</span><span class=\"p\">.</span><span class=\"nf\">Fatal</span><span class=\"p\">(</span><span class=\"nx\">err</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-15\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-15\">15</a></span><span class=\"cl\">\t<span class=\"p\">}</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-16\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-16\">16</a></span><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-17\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-17\">17</a></span><span class=\"cl\">\t<span class=\"c1\">// Retrieve a secret from the store.\n</span></span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-18\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-18\">18</a></span><span class=\"cl\"><span class=\"c1\"></span>\t<span class=\"nx\">secret</span><span class=\"p\">,</span> <span class=\"nx\">err</span> <span class=\"o\">:=</span> <span class=\"nx\">store</span><span class=\"p\">.</span><span class=\"nf\">Get</span><span class=\"p\">(</span><span class=\"s\">&#34;database-password&#34;</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-19\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-19\">19</a></span><span class=\"cl\">\t<span class=\"k\">if</span> <span class=\"nx\">err</span> <span class=\"o\">!=</span> <span class=\"kc\">nil</span> <span class=\"p\">{</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-20\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-20\">20</a></span><span class=\"cl\">\t\t<span class=\"nx\">log</span><span class=\"p\">.</span><span class=\"nf\">Fatal</span><span class=\"p\">(</span><span class=\"nx\">err</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-21\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-21\">21</a></span><span class=\"cl\">\t<span class=\"p\">}</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-22\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-22\">22</a></span><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-23\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-23\">23</a></span><span class=\"cl\">\t<span class=\"c1\">// Print the secret or do something else with it.\n</span></span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-24\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-24\">24</a></span><span class=\"cl\"><span class=\"c1\"></span>\t<span class=\"nx\">fmt</span><span class=\"p\">.</span><span class=\"nf\">Println</span><span class=\"p\">(</span><span class=\"s\">&#34;Database password:&#34;</span><span class=\"p\">,</span> <span class=\"nx\">secret</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"ln\" id=\"usage-line-25\"><a style=\"outline: none; text-decoration:none;color:inherit\" href=\"#usage-line-25\">25</a></span><span class=\"cl\"><span class=\"p\">}</span>\n</span></span></code></pre>"
},
{
"name": "xstd-go",
"description": "Small collection of extensions to Go's standard library.",
"version": "0.12.1",
"branch": "trunk",
"repository": "https://git.sr.ht/~jamesponddotco/xstd-go",
"license": "MIT"
},
{
"name": "gitignore-go",
"description": "Simple Go parser for .gitignore files.",
"version": "1.0.1",
"branch": "trunk",
"repository": "https://git.sr.ht/~jamesponddotco/gitignore-go",
"license": "MIT"
},
{
"name": "llmctx",
"description": "CLI tool that converts the content of a directory into context for LLMs.",
"version": "1.0.1",
"branch": "trunk",
"repository": "https://git.sr.ht/~jamesponddotco/llmctx",
"license": "GPL-2.0",
"hidden": true
}
]
}
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ SPDX-License-Identifier: CC0-1.0
**pkgdex** yourself.
- [Using the service](using.md): How to use the service once it is up
and running.
- [Developing the service](development.md): How to develop and
contribute code to **pkgdex**.
229 changes: 229 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
<!--
SPDX-FileCopyrightText: 2025 The Cipher Host Team <team@cipher.host>

SPDX-License-Identifier: CC-BY-SA-4.0
-->

# Development

This document provides technical guidance for developers who want to
contribute code to **pkgdex**. It complements the
[../CONTRIBUTING.md](../CONTRIBUTING.md) file by focusing specifically
on the technical aspects of development.

Before you begin, please review the
[../CONTRIBUTING.md](../CONTRIBUTING.md) file to understand the overall
contribution guidelines and our code of conduct.

## Table of Contents

1. [Development environment](#development-environment-setup)
2. [Building and Testing](#building-and-testing)
3. [Contribution Workflow](#contribution-workflow)
4. [Coding Standards](#coding-standards)
5. [Documentation](#documentation)
6. [License Compliance](#license-compliance)

## Development Environment

### Prerequisites

- Go 1.24 or above
- Node/NPM
- make
- scdoc

### Setting up your environment

1. Fork the repository on GitHub.

2. Clone your fork locally:
```bash
git clone 'https://github.com/YOUR-USERNAME/pkgdex.git'
cd 'pkgdex'
```

3. Create a development configuration file:
```bash
mkdir -p '.dev'
cp 'config/dev-config.example.json' '.dev/config.json'
```

4. Edit the `.dev/config.json` file to set appropriate development
values. You'll want to edit the following fields:

- `server.pid`
- `database.path`
- `database.indexPath`

You may also want to edit the following fields:

- `service.homepage`
- `service.baseURL`
- `server.address`

### Creating a self-signed certificate for development

Since **pkgdex** requires TLS, you'll need to generate a self-signed
certificate for local development:

```bash
openssl req -x509 -newkey rsa:4096 -keyout '.dev/pkgdex-tlskey' -out '.dev/pkgdex-tlscertificate' -days 365 -nodes -subj '/CN=localhost'
```

## Building and Testing

### Building the project

To build the project locally, run:

```bash
npm install
make
```

This will compile the binary to `build/pkgdexctl`.

For development, it's best to use the `development` target with your
development configuration in `.dev`:

```bash
make development
```

By default, this will start the service on `https://localhost:8080`, but
you can change this in the `.dev/config.json` file by modifying the
`server.address` field. You'll need to accept the self-signed
certificate warning.

> [!NOTE]
> If you modify the server address, you may also want to modify the
> `service.homepage` and `service.baseURL` fields.

### Running tests

To run the test suite:

```bash
make test
```

For test output with coverage information:

```bash
make test/coverage
```

## Contribution Workflow

As said before, review the [../CONTRIBUTING.md](../CONTRIBUTING.md) file
to understand the overall contribution guidelines and our code of
conduct.

### Creating a feature or fix

1. Ensure there's an issue for your work:
- Check [existing
issues](https://github.com/cipherdothost/pkgdex/issues) first.
- If none exists, create one clearly describing the bug or feature.

2. Create a new branch for your work in your fork:
```bash
git checkout -b 'feature/your-feature-name'
# or
git checkout -b 'fix/issue-description'
```

3. Make your changes, following the coding standards.

4. Write tests for your changes.

5. Update documentation if necessary.

6. Update the `Unreleased` section of the
[../CHANGELOG.md](../CHANGELOG.md) file.

### Submitting pull requests

1. Push your branch to your fork:
```bash
git push origin 'feature/your-feature-name'
```

2. Create a pull request against the `trunk` branch of the main
repository.

3. In your PR description:
- Clearly describe the changes.
- Reference the issue it resolves.
- Note any breaking changes or migration steps.

4. Wait for code review feedback and address any comments.

## Coding Standards

### Go code style

We like to follow both the Uber and Google Go coding standards, with a
preference for the Uber one when they conflict with each other, and we
expect your contribution to do the same.

- [Uber style guide](https://github.com/uber-go/guide/blob/master/style.md).
- [Google style guide](https://google.github.io/styleguide/go/)

### Dependencies

As mentioned in the [../CONTRIBUTING.md](../CONTRIBUTING.md) file, avoid
adding new dependencies unless absolutely necessary.

If you need to add a new dependency:

1. Ensure it's well-maintained and widely used.
2. Check its license for compatibility.
3. Update the [../LICENSE-3rdparty.csv](../LICENSE-3rdparty.csv) file.
4. Run `make tidy` to update the `go.mod` and `go.sum` files.

## Documentation

### Code documentation

- Add godoc comments to all types, functions, and methods, including
non-exported ones.
- Comments should explain the why behind the code, not just the what.
- Put the most important information first in the comment. Aim to make
the first sentence a clear, concise summary.
Focus on the intent and purpose of each part of the code.
- Use complete sentences, proper capitalization and punctuation in
comments.

### Project documentation

Project documentation is stored in the `docs/` directory:

- `hosting.md`: Instructions for deploying the service.
- `config.md`: Configuration reference.
- `using.md`: Usage instructions.
- `development.md`: Development instructions.

When updating features or APIs, make corresponding updates to the
documentation. If adding new configuration options, update `config.md`
accordingly.

## License Compliance

Remember that all code must comply with [the REUSE
specification](https://reuse.software/spec-3.3/). The default license is
[EUPL-1.2](../LICENSE.md).

Ensure each new file needs the appropriate license header. You can use
the `reuse` tool to help with this:

```bash
pipx install reuse
make lint/licenses
```

---

Thank you for contributing to **pkgdex**! Your efforts help make this
project better for everyone.
Loading