Skip to content

Commit

Permalink
Merge pull request #5 from noaccOS/feat/elixir-gen
Browse files Browse the repository at this point in the history
feat: add elixir code generation
  • Loading branch information
rbino authored Dec 6, 2023
2 parents fe44a23 + 4aadd37 commit 3c25312
Show file tree
Hide file tree
Showing 18 changed files with 337 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ jobs:
rust-check:
needs: [codegen-check]
uses: ./.github/workflows/rust-check.yaml
elixir-check:
needs: [codegen-check]
uses: ./.github/workflows/elixir-check.yaml
10 changes: 9 additions & 1 deletion .github/workflows/codegen-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ jobs:
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Install rust toolchain
uses: dtolnay/rust-toolchain@stable
- uses: erlef/setup-beam@v1
with:
otp-version: '26'
elixir-version: '1.15.7'
- name: Install elixir protobuf compiler
run: |
mix escript.install hex protobuf --force
echo "$HOME/.mix/escripts" >> "$GITHUB_PATH"
- name: Generate code
run: make all
run: make install --always-make
- name: Check diff in generated code
run: ./scripts/check_diff.sh
36 changes: 36 additions & 0 deletions .github/workflows/elixir-check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

permissions:
contents: read
on:
workflow_call:

defaults:
run:
working-directory: elixir/edgehog_device_forwarder_proto
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: '26'
elixir-version: '1.15.7'
- name: Fetch dependencies
run: mix do deps.get --only test, deps.compile
- name: Check formatting
run: mix format --check-formatted
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: '26'
elixir-version: '1.15.7'
- name: Fetch dependencies
run: mix do deps.get --only test, deps.compile
- name: Run tests
run: mix test
4 changes: 4 additions & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ Source: https://github.com/edgehog-device-manager/edgehog-device-forwarder-proto
Files: out/* rust/Cargo.lock rust/edgehog-device-forwarder-proto/src/proto.rs
Copyright: 2023 SECO Mind Srl
License: Apache-2.0

Files: elixir/edgehog_device_forwarder_proto/lib/edgehog_device_forwarder_proto/**/*.ex
Copyright: 2023 SECO Mind Srl
License: Apache-2.0
39 changes: 36 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,36 @@ CANONICAL_CURDIR = $(realpath $(CURDIR))

PROTO_DIR = $(CANONICAL_CURDIR)/proto
RUST_LANG_DIR = $(CANONICAL_CURDIR)/rust
ELIXIR_LANG_DIR = $(CANONICAL_CURDIR)/elixir
ELIXIR_LANG_LIB=$(ELIXIR_LANG_DIR)/edgehog_device_forwarder_proto/lib/edgehog_device_forwarder_proto

BASE_DIR := $(CANONICAL_O)
$(if $(BASE_DIR),, $(error output directory "$(O)" does not exist))

BUILD_DIR := $(BASE_DIR)/build
RUST_BUILD_DIR := $(BUILD_DIR)/rust
ELIXIR_BUILD_DIR := $(BUILD_DIR)/elixir

FILES=$(wildcard proto/edgehog/device/forwarder/*.proto)
FILES=$(wildcard $(PROTO_DIR)/edgehog/device/forwarder/*.proto)

PROTOC_CHECK_SCRIPT=$(CANONICAL_CURDIR)/scripts/protoc_check.sh
ELIXIR_DEPS_CHECK_SCRIPT=$(CANONICAL_CURDIR)/scripts/elixir_deps_check.sh

RUST_LANG=$(RUST_BUILD_DIR)/proto.rs
RUST_FILES=$(shell find "$(RUST_LANG_DIR)/rust-codegen" -type f -regex '.*(rs|Cargo.toml|Cargo.lock)$$') \
$(RUST_LANG_DIR)/Cargo.toml $(RUST_LANG_DIR)/Cargo.lock

ELIXIR_LANG=$(ELIXIR_BUILD_DIR)/edgehog/device/forwarder/http.pb.ex \
$(ELIXIR_BUILD_DIR)/edgehog/device/forwarder/ws.pb.ex \
$(ELIXIR_BUILD_DIR)/edgehog/device/forwarder/message.pb.ex
ELIXIR_FILES="$(ELIXIR_LANG_LIB)/edgehog/device/forwarder/"{http,ws,message}.pb.ex

# This is our default rule, so must come first
.PHONY: all
all: rust
all: rust elixir

.PHONY: install
install: rust-install
install: rust-install elixir-install

.PHONY: clean
clean:
Expand All @@ -71,6 +80,30 @@ rust-install: rust
rust-dirclean:
rm -rf $(RUST_BUILD_DIR)

$(ELIXIR_LANG) &: $(FILES)
mkdir -p $(ELIXIR_BUILD_DIR)
protoc \
--elixir_out=$(ELIXIR_BUILD_DIR) \
--elixir_opt=package_prefix=EdgehogDeviceForwarderProto \
--proto_path=$(PROTO_DIR) \
$(FILES)
mix format $(ELIXIR_LANG)

elixir-dependencies-check: $(ELIXIR_DEPS_CHECK_SCRIPT)
$(SHELL) $(ELIXIR_DEPS_CHECK_SCRIPT)

.PHONY: elixir
elixir: protoc-check elixir-dependencies-check $(ELIXIR_LANG)

.PHONY: elixir-install
elixir-install: elixir
mkdir -p "$(ELIXIR_LANG_LIB)/edgehog/device/forwarder/"
install -m 644 $(ELIXIR_LANG) "$(ELIXIR_LANG_LIB)/edgehog/device/forwarder/"

.PHONY: elixir-dirclean
elixir-dirclean:
rm -rf $(ELIXIR_BUILD_DIR)

.PHONY: help
help:
@echo 'Cleaning:'
Expand Down
7 changes: 7 additions & 0 deletions elixir/edgehog_device_forwarder_proto/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
import_deps: [:protobuf]
]
29 changes: 29 additions & 0 deletions elixir/edgehog_device_forwarder_proto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
edgehog_device_forwarder_proto-*.tar

# Temporary files, for example, from tests.
/tmp/
25 changes: 25 additions & 0 deletions elixir/edgehog_device_forwarder_proto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!--
Copyright 2023 SECO Mind Srl
SPDX-License-Identifier: Apache-2.0
-->

# EdgehogDeviceForwarderProto

**TODO: Add description**

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `edgehog_device_forwarder_proto` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:edgehog_device_forwarder_proto, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/edgehog_device_forwarder_proto>.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

defmodule EdgehogDeviceForwarderProto do
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Request.HeadersEntry do
@moduledoc false

use Protobuf, map: true, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

field(:key, 1, type: :string)
field(:value, 2, type: :string)
end

defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Request do
@moduledoc false

use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

field(:path, 1, type: :string)
field(:method, 2, type: :string)
field(:query_string, 3, type: :string, json_name: "queryString")

field(:headers, 4,
repeated: true,
type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Request.HeadersEntry,
map: true
)

field(:body, 5, type: :bytes)
field(:port, 6, type: :uint32)
end

defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Response.HeadersEntry do
@moduledoc false

use Protobuf, map: true, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

field(:key, 1, type: :string)
field(:value, 2, type: :string)
end

defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Response do
@moduledoc false

use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

field(:status_code, 1, type: :uint32, json_name: "statusCode")

field(:headers, 2,
repeated: true,
type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Response.HeadersEntry,
map: true
)

field(:body, 3, type: :bytes)
end

defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http do
@moduledoc false

use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

oneof(:message, 0)

field(:request_id, 1, type: :bytes, json_name: "requestId")

field(:request, 2,
type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Request,
oneof: 0
)

field(:response, 3,
type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http.Response,
oneof: 0
)
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Message do
@moduledoc false

use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

oneof(:protocol, 0)

field(:http, 1, type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.Http, oneof: 0)
field(:ws, 2, type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.WebSocket, oneof: 0)
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.WebSocket.Close do
@moduledoc false

use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

field(:code, 1, type: :uint32)
field(:reason, 2, type: :string)
end

defmodule EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.WebSocket do
@moduledoc false

use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"

oneof(:message, 0)

field(:socket_id, 1, type: :bytes, json_name: "socketId")
field(:text, 2, type: :string, oneof: 0)
field(:binary, 3, type: :bytes, oneof: 0)
field(:ping, 4, type: :bytes, oneof: 0)
field(:pong, 5, type: :bytes, oneof: 0)

field(:close, 6,
type: EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.WebSocket.Close,
oneof: 0
)
end
28 changes: 28 additions & 0 deletions elixir/edgehog_device_forwarder_proto/mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

defmodule EdgehogDeviceForwarderProto.MixProject do
use Mix.Project

def project do
[
app: :edgehog_device_forwarder_proto,
version: "0.0.1",
elixir: "~> 1.15",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

def application do
[
extra_applications: [:logger]
]
end

defp deps do
[
{:protobuf, "~> 0.12"}
]
end
end
3 changes: 3 additions & 0 deletions elixir/edgehog_device_forwarder_proto/mix.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
%{
"protobuf": {:hex, :protobuf, "0.12.0", "58c0dfea5f929b96b5aa54ec02b7130688f09d2de5ddc521d696eec2a015b223", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "75fa6cbf262062073dd51be44dd0ab940500e18386a6c4e87d5819a58964dc45"},
}
2 changes: 2 additions & 0 deletions elixir/edgehog_device_forwarder_proto/mix.lock.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: 2023 SECO Mind Srl
SPDX-License-Identifier: Apache-2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

defmodule EdgehogDeviceForwarderProtoTest do
use ExUnit.Case
alias EdgehogDeviceForwarderProto.Edgehog.Device.Forwarder.{Message, Http, WebSocket}
doctest EdgehogDeviceForwarderProto

test "encode and decode test" do
ws = %WebSocket{socket_id: <<>>, message: {:text, "some string"}}
assert ws == ws |> WebSocket.encode() |> WebSocket.decode()

http_response = %Http.Response{status_code: 200, headers: %{}, body: <<>>}
http = %Http{request_id: <<>>, message: {:response, http_response}}

assert http == http |> Http.encode() |> Http.decode()

message = %Message{protocol: {:ws, ws}}
assert message == message |> Message.encode() |> Message.decode()
assert {:ws, ^ws} = message |> Message.encode() |> Message.decode() |> Map.get(:protocol)
end
end
4 changes: 4 additions & 0 deletions elixir/edgehog_device_forwarder_proto/test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2023 SECO Mind Srl
# SPDX-License-Identifier: Apache-2.0

ExUnit.start()
Loading

0 comments on commit 3c25312

Please sign in to comment.